From 53b60172fbddd1d557d831586c86b7b815331bfb Mon Sep 17 00:00:00 2001 From: Shlomi Noach Date: Fri, 1 Apr 2016 10:43:50 +0200 Subject: [PATCH] overcoming MySQL stored routines bug with local variables --- build.xml | 90 ++++++++++--------- routines/script/_consume_expression.sql | 24 ++--- .../script/_consume_foreach_expression.sql | 28 +++--- routines/script/_consume_split_statement.sql | 33 ++++--- .../_consume_split_statement_params.sql | 9 +- routines/script/_consume_statement.sql | 72 ++++++++------- routines/script/_interpret.sql | 40 +++++---- ...ve_and_consume_sql_or_script_statement.sql | 8 +- routines/script/_run_named_script.sql | 6 +- routines/script/_throw_script_error.sql | 6 +- routines/script/array/_create_array.sql | 6 +- routines/script/array/_get_array_element.sql | 6 +- routines/script/array/_get_array_size.sql | 6 +- .../_consume_function_call_statement.sql | 60 ++++++++----- .../_consume_function_expression.sql | 23 +++-- .../functions/_expect_function_exists.sql | 5 +- ...t_assign_initial_range_start_variables.sql | 17 ++-- .../split/_split_assign_min_max_variables.sql | 48 +++++----- ...plit_assign_next_range_start_variables.sql | 13 +-- .../script/split/_split_deduce_columns.sql | 32 +++---- .../_split_get_columns_comparison_clause.sql | 39 ++++---- .../script/split/_split_get_columns_count.sql | 15 ++-- .../script/split/_split_get_columns_names.sql | 15 ++-- ...lit_get_columns_order_ascending_clause.sql | 15 ++-- ...it_get_columns_order_descending_clause.sql | 15 ++-- .../split/_split_get_max_variables_names.sql | 15 ++-- .../split/_split_get_min_variables_names.sql | 15 ++-- .../_split_get_range_end_variables_names.sql | 15 ++-- ..._split_get_range_start_variables_names.sql | 15 ++-- .../script/split/_split_init_variables.sql | 15 ++-- ...t_split_query_table_definitions_clause.sql | 38 ++++---- .../split/analyze/_get_split_query_type.sql | 19 ++-- ...it_single_table_from_table_definitions.sql | 27 +++--- .../analyze/_inject_split_where_token.sql | 57 ++++++------ routines/script/states/_consume_if_exists.sql | 7 +- routines/script/states/_match_states.sql | 28 +++--- routines/script/states/_skip_empty_spaces.sql | 9 +- routines/script/states/_skip_states.sql | 11 +-- .../script/states/_validate_statement_end.sql | 13 +-- .../_assign_input_local_variables.sql | 22 ++--- .../_declare_and_assign_local_variable.sql | 37 ++++---- .../variables/_declare_local_variable.sql | 18 ++-- .../variables/_declare_local_variables.sql | 23 ++--- .../variables/_expand_single_variable.sql | 23 ++--- .../variables/_expand_statement_variables.sql | 34 +++---- .../_take_local_variables_snapshot.sql | 22 ++--- .../debugged_routines/01/description.txt | 0 .../debugged_routines/01/test.sql | 0 .../debugged_routines/02/description.txt | 0 .../debugged_routines/02/test.sql | 0 .../debugged_routines/pre.sql | 0 .../rdebug_compile_routine/01/description.txt | 0 .../rdebug_compile_routine/01/test.sql | 0 .../rdebug_compile_routine/02/description.txt | 0 .../rdebug_compile_routine/02/test.sql | 0 .../rdebug_compile_routine/03/description.txt | 0 .../rdebug_compile_routine/03/test.sql | 0 .../rdebug_compile_routine/04/description.txt | 0 .../rdebug_compile_routine/04/test.sql | 0 .../rdebug_compile_routine/05/description.txt | 0 .../rdebug_compile_routine/05/test.sql | 0 .../rdebug_compile_routine/06/description.txt | 0 .../rdebug_compile_routine/06/test.sql | 0 .../rdebug_compile_routine/07/description.txt | 0 .../rdebug_compile_routine/07/test.sql | 0 .../rdebug_compile_routine/pre.sql | 0 .../sql_range_partitions/01/description.txt | 0 .../sql_range_partitions/01/expected.txt | 0 .../sql_range_partitions/01/test.sql | 0 .../sql_range_partitions/02/description.txt | 0 .../sql_range_partitions/02/expected.txt | 0 .../sql_range_partitions/02/test.sql | 0 .../sql_range_partitions/03/description.txt | 0 .../sql_range_partitions/03/expected.txt | 0 .../sql_range_partitions/03/test.sql | 0 .../sql_range_partitions/04/description.txt | 0 .../sql_range_partitions/04/expected.txt | 0 .../sql_range_partitions/04/pre.sql | 0 .../sql_range_partitions/04/test.sql | 0 .../sql_range_partitions/05/description.txt | 0 .../sql_range_partitions/05/expected.txt | 0 .../sql_range_partitions/05/test.sql | 0 .../sql_range_partitions/06/description.txt | 0 .../sql_range_partitions/06/expected.txt | 0 .../sql_range_partitions/06/pre.sql | 0 .../sql_range_partitions/06/test.sql | 0 .../sql_range_partitions/07/description.txt | 0 .../sql_range_partitions/07/expected.txt | 0 .../sql_range_partitions/07/test.sql | 0 .../sql_range_partitions/08/description.txt | 0 .../sql_range_partitions/08/expected.txt | 0 .../sql_range_partitions/08/test.sql | 0 .../sql_range_partitions/09/description.txt | 0 .../sql_range_partitions/09/expected.txt | 0 .../sql_range_partitions/09/test.sql | 0 .../sql_range_partitions/10/description.txt | 0 .../sql_range_partitions/10/test.sql | 0 .../sql_range_partitions/11/description.txt | 0 .../sql_range_partitions/11/test.sql | 0 .../sql_range_partitions/12/description.txt | 0 .../sql_range_partitions/12/test.sql | 0 .../sql_range_partitions/13/description.txt | 0 .../sql_range_partitions/13/test.sql | 0 .../sql_range_partitions/14/description.txt | 0 .../sql_range_partitions/14/expected.txt | 0 .../sql_range_partitions/14/test.sql | 0 .../sql_range_partitions/pre.sql | 0 tests/test_all.sh | 21 ++--- 108 files changed, 622 insertions(+), 493 deletions(-) rename tests/{root => __legacy__}/debugged_routines/01/description.txt (100%) rename tests/{root => __legacy__}/debugged_routines/01/test.sql (100%) rename tests/{root => __legacy__}/debugged_routines/02/description.txt (100%) rename tests/{root => __legacy__}/debugged_routines/02/test.sql (100%) rename tests/{root => __legacy__}/debugged_routines/pre.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/01/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/01/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/02/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/02/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/03/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/03/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/04/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/04/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/05/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/05/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/06/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/06/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/07/description.txt (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/07/test.sql (100%) rename tests/{root => __legacy__}/rdebug_compile_routine/pre.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/01/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/01/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/01/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/02/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/02/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/02/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/03/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/03/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/03/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/04/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/04/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/04/pre.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/04/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/05/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/05/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/05/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/06/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/06/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/06/pre.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/06/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/07/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/07/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/07/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/08/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/08/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/08/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/09/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/09/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/09/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/10/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/10/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/11/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/11/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/12/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/12/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/13/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/13/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/14/description.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/14/expected.txt (100%) rename tests/{root => __legacy__}/sql_range_partitions/14/test.sql (100%) rename tests/{root => __legacy__}/sql_range_partitions/pre.sql (100%) diff --git a/build.xml b/build.xml index 0bd2663..b9df0f7 100644 --- a/build.xml +++ b/build.xml @@ -6,16 +6,16 @@ - + +--> - + - - - - + + + @@ -49,20 +49,20 @@ - + - + - + - + @@ -70,7 +70,7 @@ - + @@ -90,7 +90,7 @@ revision: ${svn.revision} - + @@ -118,15 +118,15 @@ + + --> - + @@ -139,8 +139,8 @@ - - + + @@ -164,32 +164,32 @@ - + - + - + - + - + - + - + @@ -198,7 +198,7 @@ - + @@ -212,7 +212,7 @@ - + @@ -220,22 +220,22 @@ - + - - + + - + - + @@ -259,6 +259,7 @@ + @@ -273,11 +274,12 @@ + - + @@ -310,7 +312,7 @@ - + @@ -320,9 +322,9 @@ - + - + @@ -332,10 +334,10 @@ - + - - + + @@ -352,7 +354,7 @@ - + @@ -375,7 +377,7 @@ - + Testing @@ -385,8 +387,8 @@ - - + + ${basedir} ${abc} @@ -397,4 +399,4 @@ prop2: ---${f.c2}--- - \ No newline at end of file + diff --git a/routines/script/_consume_expression.sql b/routines/script/_consume_expression.sql index db02940..ee33575 100644 --- a/routines/script/_consume_expression.sql +++ b/routines/script/_consume_expression.sql @@ -23,32 +23,36 @@ sql security invoker main_body: begin declare first_state text; declare expression_level int unsigned; - declare id_end_expression int unsigned; + declare id_end_expression int unsigned; declare expanded_variables TEXT CHARSET utf8; declare expanded_variables_found tinyint unsigned; - + set expression_statement := NULL ; - + call _skip_spaces(id_from, id_to); - SELECT level, state FROM _sql_tokens WHERE id = id_from INTO expression_level, first_state; + set @_expression_level=null, @_first_state=null; + SELECT level, state FROM _sql_tokens WHERE id = id_from INTO @_expression_level, @_first_state; + set expression_level=@_expression_level; + set first_state=@_first_state; if (first_state = 'left parenthesis') then - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO id_end_expression; + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO @_id_end_expression; + set id_end_expression=@_id_end_expression; if id_end_expression IS NULL then call _throw_script_error(id_from, 'Unmatched "(" parenthesis'); end if; set id_from := id_from + 1; call _skip_spaces(id_from, id_to); - + call _expand_statement_variables(id_from, id_end_expression-1, expression, expanded_variables_found, should_execute_statement); - -- SELECT GROUP_CONCAT(token ORDER BY id SEPARATOR '') FROM _sql_tokens WHERE id BETWEEN id_from AND id_end_expression-1 INTO expression; - + -- Note down the statement (if any) of the expression: - SELECT token FROM _sql_tokens WHERE id = id_from AND state = 'alpha' INTO expression_statement; + set @_expression_statement=null; + SELECT token FROM _sql_tokens WHERE id = id_from AND state = 'alpha' INTO @_expression_statement; + set expression_statement=@_expression_statement; if ((expression is NULL) or (trim_wspace(expression) = '')) and (should_execute_statement or not expanded_variables_found) then call _throw_script_error(id_from, 'Found empty expression'); end if; - -- ~~~ select expression, expression_statement; set consumed_to_id := id_end_expression; else if require_parenthesis then diff --git a/routines/script/_consume_foreach_expression.sql b/routines/script/_consume_foreach_expression.sql index 3b85108..31fcea4 100644 --- a/routines/script/_consume_foreach_expression.sql +++ b/routines/script/_consume_foreach_expression.sql @@ -24,40 +24,44 @@ sql security invoker main_body: begin declare first_state text; declare expression_level int unsigned; - declare id_end_expression int unsigned default NULL; - declare id_end_variables_definition int unsigned default NULL; - + declare id_end_expression int unsigned default NULL; + declare id_end_variables_definition int unsigned default NULL; + call _skip_spaces(id_from, id_to); - SELECT level, state FROM _sql_tokens WHERE id = id_from INTO expression_level, first_state; + set @_expression_level=null, @_first_state=null; + SELECT level, state FROM _sql_tokens WHERE id = id_from INTO @_expression_level, @_first_state; + set expression_level=@_expression_level; + set first_state=@_first_state; if (first_state != 'left parenthesis') then call _throw_script_error(id_from, 'Expected "(" on foreach expression'); end if; - - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO id_end_expression; + + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO @_id_end_expression; + set id_end_expression=@_id_end_expression; if id_end_expression IS NULL then call _throw_script_error(id_from, 'Unmatched "(" parenthesis'); end if; - + -- Detect the positions where variables are declared - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'colon' AND level = expression_level INTO id_end_variables_definition; + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'colon' AND level = expression_level INTO @_id_end_variables_definition; + set id_end_variables_definition=@_id_end_variables_definition; if id_end_variables_definition IS NULL then call _throw_script_error(id_from, 'foreach: expected ":" as in (variables : collection)'); end if; - + set id_from := id_from + 1; - + -- Expect variables declaration: call _expect_dynamic_states_list(id_from, id_end_variables_definition-1, 'query_script variable', variables_array_id); set variables_delaration_id := id_from; call _declare_local_variables(id_from, id_to, id_end_variables_definition, depth, _implode_nospace_array(variables_array_id)); - + -- Get the collection clause: set id_from := id_end_variables_definition + 1; call _skip_spaces(id_from, id_to); call _expand_statement_variables(id_from, id_end_expression-1, collection, @_common_schema_dummy, should_execute_statement); - -- SELECT GROUP_CONCAT(token ORDER BY id SEPARATOR '') FROM _sql_tokens WHERE id BETWEEN id_from AND id_end_expression-1 INTO collection; set consumed_to_id := id_end_expression; end; diff --git a/routines/script/_consume_split_statement.sql b/routines/script/_consume_split_statement.sql index 8629205..ec19dc0 100644 --- a/routines/script/_consume_split_statement.sql +++ b/routines/script/_consume_split_statement.sql @@ -26,39 +26,44 @@ sql security invoker main_body: begin declare first_state text; declare expression_level int unsigned; - declare id_end_action_statement int unsigned default NULL; - declare id_end_split_table_declaration int unsigned default NULL; + declare id_end_action_statement int unsigned default NULL; + declare id_end_split_table_declaration int unsigned default NULL; declare query_type_supported tinyint unsigned; declare tables_found varchar(32) charset ascii; declare colon_exists tinyint unsigned default false; declare found_explicit_table tinyint unsigned; declare found_any_params tinyint unsigned; declare found_possible_statement tinyint unsigned; - + call _skip_spaces(id_from, id_to); - SELECT level, state FROM _sql_tokens WHERE id = id_from INTO expression_level, first_state; + set @_expression_level=null, @_first_state=null; + SELECT level, state FROM _sql_tokens WHERE id = id_from INTO @_expression_level, @_first_state; + set expression_level=@_expression_level; + set first_state=@_first_state; -- Validate syntax: if (first_state != 'left parenthesis') then call _throw_script_error(id_from, 'Expected "(" on split expression'); end if; - - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO id_end_action_statement; + + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO @_id_end_action_statement; + set id_end_action_statement=@_id_end_action_statement; if id_end_action_statement IS NULL then call _throw_script_error(id_from, 'Unmatched "(" parenthesis'); end if; - + -- Detect the separator: - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'colon' AND level = expression_level INTO id_end_split_table_declaration; + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'colon' AND level = expression_level INTO @_id_end_split_table_declaration; + set id_end_split_table_declaration=@_id_end_split_table_declaration; set colon_exists := (id_end_split_table_declaration IS NOT NULL); if id_end_split_table_declaration IS NULL then set id_end_split_table_declaration := id_end_action_statement; end if; - + set id_from := id_from + 1; - + set split_injected_text := '[:_query_script_split_injected_placeholder:]'; - + set found_possible_statement := true; if colon_exists then call _consume_split_statement_params(id_from, id_end_split_table_declaration-1, should_execute_statement, split_table_schema, split_table_name, split_options, found_explicit_table, found_any_params); @@ -77,11 +82,11 @@ main_body: begin set found_possible_statement := false; end if; end if; - + if not (found_possible_statement or found_explicit_table) then call _throw_script_error(id_from, 'split: no statement nor table provided. Provide at least either one'); end if; - + if found_possible_statement then if not found_explicit_table then call _skip_spaces(id_from, id_end_action_statement - 1); @@ -97,7 +102,7 @@ main_body: begin else set split_injected_action_statement := CONCAT('SELECT COUNT(NULL) FROM ', mysql_qualify(split_table_schema), '.', mysql_qualify(split_table_name), ' WHERE ', split_injected_text, ' INTO @_common_schema_dummy'); end if; - + set consumed_to_id := id_end_action_statement; end; // diff --git a/routines/script/_consume_split_statement_params.sql b/routines/script/_consume_split_statement_params.sql index a22ef08..d66df3e 100644 --- a/routines/script/_consume_split_statement_params.sql +++ b/routines/script/_consume_split_statement_params.sql @@ -24,7 +24,7 @@ sql security invoker main_body: begin declare expanded_statement mediumtext charset utf8; declare options_value mediumtext charset utf8; - + call _skip_spaces(id_from, id_to); set split_table_schema := null; @@ -33,7 +33,6 @@ main_body: begin set found_explicit_table := false; call _expand_statement_variables(id_from, id_to, expanded_statement, @_common_schema_dummy, should_execute_statement); - -- select GROUP_CONCAT(token order by id separator '') from _sql_tokens where id between id_from AND id_to into split_options; if _is_options_format(expanded_statement) then set split_options := expanded_statement; set options_value := get_option(split_options, 'table'); @@ -49,14 +48,14 @@ main_body: begin else begin -- watch out for table_schema.table_name - declare peek_match_to int unsigned default NULL; + declare peek_match_to int unsigned default NULL; declare table_array_id varchar(16); - + call _create_array(table_array_id); call _peek_states_list(id_from, id_to, 'alpha|alphanum|quoted identifier|expanded query_script variable,dot,alpha|alphanum|quoted identifier|expanded query_script variable', false, false, true, table_array_id, peek_match_to); if peek_match_to > 0 then -- we have table_schema.table_name, and no statement - call _get_array_element(table_array_id, '1', split_table_schema); + call _get_array_element(table_array_id, '1', split_table_schema); call _get_array_element(table_array_id, '3', split_table_name); call _expand_single_variable(id_from, id_to, split_table_schema, should_execute_statement); call _expand_single_variable(id_from, id_to, split_table_name, should_execute_statement); diff --git a/routines/script/_consume_statement.sql b/routines/script/_consume_statement.sql index 3244332..0c24514 100644 --- a/routines/script/_consume_statement.sql +++ b/routines/script/_consume_statement.sql @@ -24,24 +24,24 @@ main_body: begin declare first_token text; declare first_state text; declare statement_level int unsigned; - declare id_end_statement int unsigned; - + declare id_end_statement int unsigned; + declare statement_delimiter_found tinyint unsigned; - + declare expression text charset utf8; declare expression_statement text charset utf8; declare expression_result tinyint unsigned; - + declare peek_match tinyint unsigned; declare matched_token text charset utf8; - + declare loop_iteration_count bigint unsigned; - + declare while_statement_id_from int unsigned; declare while_statement_id_to int unsigned; declare while_otherwise_statement_id_from int unsigned; declare while_otherwise_statement_id_to int unsigned; - + declare foreach_statement_id_from int unsigned; declare foreach_statement_id_to int unsigned; declare foreach_otherwise_statement_id_from int unsigned; @@ -49,7 +49,7 @@ main_body: begin declare function_statement_id_from int unsigned; declare function_statement_id_to int unsigned; - + declare split_statement_id_from int unsigned; declare split_statement_id_to int unsigned; declare split_options varchar(2048) charset utf8; @@ -58,7 +58,7 @@ main_body: begin declare if_statement_id_to int unsigned; declare else_statement_id_from int unsigned; declare else_statement_id_to int unsigned; - + declare try_statement_error_found tinyint unsigned; declare try_statement_id_from int unsigned; declare try_statement_id_to int unsigned; @@ -74,12 +74,12 @@ main_body: begin declare function_arguments_declaration_id int unsigned; declare function_declaration_id int unsigned; declare declared_function_name text charset utf8; - + declare split_table_schema tinytext charset utf8; declare split_table_name tinytext charset utf8; declare split_injected_action_statement text charset utf8; declare split_injected_text text charset utf8; - + declare reset_query text charset utf8; if is_loop then @@ -91,7 +91,11 @@ main_body: begin leave statement_loop; end if; - SELECT level, token, state FROM _sql_tokens WHERE id = id_from INTO statement_level, first_token, first_state; + set @_statement_level=null, @_first_token=null, @_first_state=null; + SELECT level, token, state FROM _sql_tokens WHERE id = id_from INTO @_statement_level, @_first_token, @_first_state; + set statement_level=@_statement_level; + set first_token=@_first_token; + set first_state=@_first_state; case when first_state in ('whitespace', 'single line comment', 'multi line comment') then begin @@ -101,7 +105,8 @@ main_body: begin end; when first_state = 'left braces' then begin -- Start new block - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right braces' AND level = statement_level INTO id_end_statement; + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right braces' AND level = statement_level INTO @_id_end_statement; + set id_end_statement=@_id_end_statement; if id_end_statement IS NULL then call _throw_script_error(id_from, 'Unmatched "{" brace'); end if; @@ -203,11 +208,11 @@ main_body: begin set foreach_statement_id_from := id_from; set foreach_statement_id_to := consumed_to_id; - update - _qs_variables - set - scope_end_id = foreach_statement_id_to - where + update + _qs_variables + set + scope_end_id = foreach_statement_id_to + where declaration_id = foreach_variables_delaration_id and (function_scope = _get_current_variables_function_scope()) ; @@ -310,7 +315,7 @@ main_body: begin else call _throw_script_error(id_from, CONCAT('Expected "catch" on try-catch block')); end if; - + if should_execute_statement then call _consume_try_statement(try_statement_id_from, try_statement_id_to, TRUE, @_common_schema_dummy, depth+1, TRUE, try_statement_error_found); if try_statement_error_found then @@ -337,7 +342,9 @@ main_body: begin end if; set consumed_to_id := id_from; end; - else begin + else begin + select * from _sql_tokens; + select first_state; call _throw_script_error(id_from, CONCAT('Unsupported token: "', first_token, '"')); end; end case; @@ -350,24 +357,25 @@ main_body: begin if is_loop then set @_common_schema_script_loop_nesting_level := @_common_schema_script_loop_nesting_level - 1; end if; - + -- End of scope -- Reset local variables: remove mapping to user-defined-variables; reset value snapshots if any. - SELECT - GROUP_CONCAT('SET ', mapped_user_defined_variable_name, ' := NULL ' SEPARATOR ';') - FROM - _qs_variables - WHERE + SELECT + GROUP_CONCAT('SET ', mapped_user_defined_variable_name, ' := NULL ' SEPARATOR ';') + FROM + _qs_variables + WHERE declaration_depth = depth and (function_scope = _get_current_variables_function_scope()) - INTO reset_query; + INTO @_reset_query; + set reset_query=@_reset_query; call exec(reset_query); - UPDATE - _qs_variables - SET - value_snapshot = NULL - WHERE + UPDATE + _qs_variables + SET + value_snapshot = NULL + WHERE declaration_depth = depth and (function_scope = _get_current_variables_function_scope()) ; diff --git a/routines/script/_interpret.sql b/routines/script/_interpret.sql index 66b6ea7..4c1d0ed 100644 --- a/routines/script/_interpret.sql +++ b/routines/script/_interpret.sql @@ -32,39 +32,45 @@ main_body: begin RESIGNAL; END; */ - + set @@max_sp_recursion_depth := 127; set @__script_group_concat_max_len := @@group_concat_max_len; set @@group_concat_max_len := GREATEST(@@group_concat_max_len, 32 * 1024 * 1024); - + call _get_sql_tokens(query_script); - SELECT MIN(id), MAX(id) FROM _sql_tokens INTO id_from, id_to; - SELECT MIN(id) FROM _sql_tokens WHERE level < 0 INTO negative_level_id; + SELECT MIN(id), MAX(id) FROM _sql_tokens INTO @_id_from, @_id_to; + set id_from=@_id_from; + set id_to=@_id_to; + SELECT MIN(id) FROM _sql_tokens WHERE level < 0 INTO @_negative_level_id; + set negative_level_id=@_negative_level_id; if negative_level_id IS NOT NULL then call throw(CONCAT('Negative nesting level detected at id ', negative_level_id)); end if; - SELECT level FROM _sql_tokens WHERE id = id_to INTO end_level; + set @_end_level=null; + SELECT level FROM _sql_tokens WHERE id = id_to INTO @_end_level; + set end_level=@_end_level; if end_level != 0 then call throw('Invalid nesting level detected at end of script'); end if; delete from _qs_variables; delete from _qs_functions; - + -- Identify ${my_var} expanded variables. These are initially not identified as a state. -- We hack the _sql_tokens table to make these in their own state, combining multiple rows into one, -- leaving previously occupied rows as empty strings. - select group_concat(id order by id) from _sql_tokens where state='expanded query_script variable' and token=':$' into expanded_variables_ids; + select group_concat(id order by id) from _sql_tokens where state='expanded query_script variable' and token=':$' into @_expanded_variables_ids; + set expanded_variables_ids=@_expanded_variables_ids; if expanded_variables_ids then set num_expanded_variables_ids := get_num_tokens(expanded_variables_ids, ','); set expanded_variable_index := 1; while expanded_variable_index <= num_expanded_variables_ids do set current_expanded_variable_id := split_token(expanded_variables_ids, ',', expanded_variable_index); - select - GROUP_CONCAT(token ORDER BY id SEPARATOR '') AS expanded_variable_tokens, + select + GROUP_CONCAT(token ORDER BY id SEPARATOR '') AS expanded_variable_tokens, ( GROUP_CONCAT(state ORDER BY id) = 'left braces,alpha,right braces' OR - GROUP_CONCAT(state ORDER BY id) = 'left braces,alphanum,right braces' + GROUP_CONCAT(state ORDER BY id) = 'left braces,alphanum,right braces' ) AS expanded_variable_match from _sql_tokens where id between current_expanded_variable_id+1 and current_expanded_variable_id+3 into @_expanded_variable_tokens, @_expanded_variable_match; @@ -75,11 +81,11 @@ main_body: begin update _sql_tokens set token = CONCAT(':$', @_expanded_variable_tokens) where id = current_expanded_variable_id; update _sql_tokens set token = '', state = 'whitespace', level = level - 1 where id between current_expanded_variable_id+1 and current_expanded_variable_id+3; end if; - + set expanded_variable_index := expanded_variable_index + 1; - end while; + end while; end if; - + set @_common_schema_script_break_type := NULL; set @_common_schema_script_loop_nesting_level := 0; set @_common_schema_script_function_stack_level := 0; @@ -89,11 +95,11 @@ main_body: begin set @_common_schema_script_report_used := false; set @_common_schema_script_report_delimiter := ''; - -- We happen to know tokens in _sql_tokens begin at "1". So "0" is a safe + -- We happen to know tokens in _sql_tokens begin at "1". So "0" is a safe -- place not to step on anyone's toes. call _declare_local_variable(0, 0, id_to, 0, '$rowcount', '@query_script_rowcount', FALSE); call _declare_local_variable(0, 0, id_to, 0, '$found_rows', '@query_script_found_rows', FALSE); - + -- First, do syntax validation: go through the code, but execute nothing: call _consume_statement(id_from, id_to, FALSE, id_to, 0, false, FALSE); -- Now, if need be, execute it: @@ -101,11 +107,11 @@ main_body: begin -- delete from _qs_variables; call _consume_statement(id_from, id_to, FALSE, id_to, 0, false, TRUE); end if; - + if @_common_schema_script_report_used then call _script_report_finalize(); end if; - + set @@group_concat_max_len := @__script_group_concat_max_len; call _cleanup_script_tables(); end; diff --git a/routines/script/_resolve_and_consume_sql_or_script_statement.sql b/routines/script/_resolve_and_consume_sql_or_script_statement.sql index fa9e5b0..7de14f4 100644 --- a/routines/script/_resolve_and_consume_sql_or_script_statement.sql +++ b/routines/script/_resolve_and_consume_sql_or_script_statement.sql @@ -25,9 +25,11 @@ sql security invoker main_body: begin declare resolve_statement_type text charset utf8; declare token_has_matched tinyint unsigned default FALSE; - - select statement_type from _script_statements where statement = statement_token into resolve_statement_type; - + + set @_resolve_statement_type=null; + select statement_type from _script_statements where statement = statement_token into @_resolve_statement_type; + set resolve_statement_type=@_resolve_statement_type; + case resolve_statement_type when 'sql' then begin call _consume_sql_statement(id_from, statement_id_to, should_execute_statement); diff --git a/routines/script/_run_named_script.sql b/routines/script/_run_named_script.sql index b55ace3..cdfcb55 100644 --- a/routines/script/_run_named_script.sql +++ b/routines/script/_run_named_script.sql @@ -17,8 +17,10 @@ sql security invoker main_body: begin declare query_script text charset utf8; - - select script_text from _named_scripts where script_name = named_script_name into query_script; + + set @_query_script=null; + select script_text from _named_scripts where script_name = named_script_name into @_query_script; + set query_script=@_query_script; if query_script is null then call throw(CONCAT('Unknown script: ', named_script_name)); end if; diff --git a/routines/script/_throw_script_error.sql b/routines/script/_throw_script_error.sql index c4e6638..1406036 100644 --- a/routines/script/_throw_script_error.sql +++ b/routines/script/_throw_script_error.sql @@ -20,8 +20,10 @@ main_body: begin declare full_message varchar(2048); declare error_pos int unsigned; - SELECT LEFT(GROUP_CONCAT(token ORDER BY id SEPARATOR ''), 80), SUBSTRING_INDEX(GROUP_CONCAT(start ORDER BY id), ',', 1) FROM _sql_tokens WHERE id >= id_from INTO full_message, error_pos; - + SELECT LEFT(GROUP_CONCAT(token ORDER BY id SEPARATOR ''), 80), SUBSTRING_INDEX(GROUP_CONCAT(start ORDER BY id), ',', 1) FROM _sql_tokens WHERE id >= id_from INTO @_full_message, @_error_pos; + set full_message=@_full_message; + set error_pos=@_error_pos; + set full_message := CONCAT('QueryScript error: [', message, '] at ', error_pos, ': "', full_message, '"'); call throw(full_message); end; diff --git a/routines/script/array/_create_array.sql b/routines/script/array/_create_array.sql index 07d4ba6..bc863d8 100644 --- a/routines/script/array/_create_array.sql +++ b/routines/script/array/_create_array.sql @@ -7,7 +7,7 @@ drop procedure if exists _create_array // create procedure _create_array( out array_id VARCHAR(16) charset ascii -) +) comment 'Creates an array, returning its ID' language SQL deterministic @@ -15,7 +15,9 @@ modifies sql data sql security invoker main_body: begin - select _create_mxarray() into array_id; + set @_array_id=null; + select _create_mxarray() into @_array_id; + set array_id=@_array_id; end; // diff --git a/routines/script/array/_get_array_element.sql b/routines/script/array/_get_array_element.sql index 985d5a4..a5555d5 100644 --- a/routines/script/array/_get_array_element.sql +++ b/routines/script/array/_get_array_element.sql @@ -9,7 +9,7 @@ create procedure _get_array_element( in array_id VARCHAR(16) charset ascii, in array_key varchar(127) charset utf8, out element text charset utf8 -) +) comment 'Creates an array, returning its ID' language SQL deterministic @@ -17,7 +17,9 @@ reads sql data sql security invoker main_body: begin - select _get_mxarray_element(array_id, array_key) into element; + set @_element=null; + select _get_mxarray_element(array_id, array_key) into @_element; + set element=@_element; end; // diff --git a/routines/script/array/_get_array_size.sql b/routines/script/array/_get_array_size.sql index 6dc6886..e099511 100644 --- a/routines/script/array/_get_array_size.sql +++ b/routines/script/array/_get_array_size.sql @@ -8,7 +8,7 @@ drop procedure if exists _get_array_size // create procedure _get_array_size( in array_id VARCHAR(16) charset ascii, out array_size int unsigned -) +) comment 'Creates an array, returning its ID' language SQL deterministic @@ -16,7 +16,9 @@ reads sql data sql security invoker main_body: begin - select _get_mxarray_size(array_id) into array_size; + set @_array_size=null; + select _get_mxarray_size(array_id) into @_array_size; + set array_size=@_array_size; end; // diff --git a/routines/script/functions/_consume_function_call_statement.sql b/routines/script/functions/_consume_function_call_statement.sql index e550b4c..9ea0e18 100644 --- a/routines/script/functions/_consume_function_call_statement.sql +++ b/routines/script/functions/_consume_function_call_statement.sql @@ -37,7 +37,7 @@ main_body: begin declare push_query text charset utf8; declare mapped_user_defined_variable_names text charset utf8; declare counter int unsigned; - + call _expect_state(statement_id_from, statement_id_to, 'alpha|alphanum', true, consumed_to_id, matched_function_name); call _expect_function_exists(statement_id_from, matched_function_name); if should_execute_statement then @@ -52,58 +52,76 @@ main_body: begin set statement_arguments := unwrap(statement_arguments); set statement_arguments := trim_wspace(statement_arguments); + set + @_expected_num_arguments=null, + @_imploded_function_arguments=null, + @_function_arguments_declaration_id=null, + @_function_scope_start_id=null, + @_function_scope_end_id=null + ; -- grab hold of info: - select + select count_function_arguments, function_arguments, arguments_declaration_id, - scope_start_id, + scope_start_id, scope_end_id from _qs_functions where function_name = matched_function_name - into - expected_num_arguments, - imploded_function_arguments, - function_arguments_declaration_id, - function_scope_start_id, - function_scope_end_id + into + @_expected_num_arguments, + @_imploded_function_arguments, + @_function_arguments_declaration_id, + @_function_scope_start_id, + @_function_scope_end_id ; + set + expected_num_arguments=@_expected_num_arguments, + imploded_function_arguments=@_imploded_function_arguments, + function_arguments_declaration_id=@_function_arguments_declaration_id, + function_scope_start_id=@_function_scope_start_id, + function_scope_end_id=@_function_scope_end_id + ; -- validate num arguments provided is same as in function declaration if statement_arguments = '' then set num_arguments := 0; else - select - count(*) - from + set @_num_arguments=null; + select + count(*) + from _sql_tokens, (select level as arguments_level from _sql_tokens where id = statement_id_from) sel_arguments_level - where + where id >= statement_id_from and id <= statement_id_to and state = 'comma' and level = arguments_level - into num_arguments; + into @_num_arguments; + set num_arguments=@_num_arguments; set num_arguments := num_arguments + 1; end if; - + if num_arguments != expected_num_arguments then call _throw_script_error(id_from, concat('Expected ', expected_num_arguments, ' arguments, found ', num_arguments)); end if; - + call _push_current_variables_function_scope(matched_function_name); call _declare_local_variables(function_arguments_declaration_id, function_scope_end_id, function_scope_end_id, depth, imploded_function_arguments); -- push values into function arguments: - select + set @_mapped_user_defined_variable_names=null; + select group_concat(mapped_user_defined_variable_name order by mapped_user_defined_variable_name separator ',') - from + from _qs_variables - where + where declaration_id = function_arguments_declaration_id and (function_scope = _get_current_variables_function_scope()) - into - mapped_user_defined_variable_names; + into + @_mapped_user_defined_variable_names; + set mapped_user_defined_variable_names=@_mapped_user_defined_variable_names; set push_query := concat('select ', statement_arguments, ' into ', mapped_user_defined_variable_names); call exec(push_query); diff --git a/routines/script/functions/_consume_function_expression.sql b/routines/script/functions/_consume_function_expression.sql index 2d49c66..9e62c3d 100644 --- a/routines/script/functions/_consume_function_expression.sql +++ b/routines/script/functions/_consume_function_expression.sql @@ -24,26 +24,31 @@ sql security invoker main_body: begin declare first_state text; declare expression_level int unsigned; - declare id_end_expression int unsigned default NULL; - declare id_end_variables_definition int unsigned default NULL; + declare id_end_expression int unsigned default NULL; + declare id_end_variables_definition int unsigned default NULL; declare count_functions tinyint unsigned default 0; - + call _skip_spaces(id_from, id_to); call _expect_state(id_from, id_from, 'alpha|alphanum', false, consumed_to_id, function_name); - + set id_from := id_from + 1; call _skip_spaces(id_from, id_to); - SELECT level, state FROM _sql_tokens WHERE id = id_from INTO expression_level, first_state; + set @_expression_level=null, @_first_state=null; + SELECT level, state FROM _sql_tokens WHERE id = id_from INTO @_expression_level, @_first_state; + set expression_level=@_expression_level; + set first_state=@_first_state; if (first_state != 'left parenthesis') then call _throw_script_error(id_from, 'Expected "(" on function expression'); end if; - - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO id_end_expression; + + set @_id_end_expression=null; + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND state = 'right parenthesis' AND level = expression_level INTO @_id_end_expression; + set id_end_expression=@_id_end_expression; if id_end_expression IS NULL then call _throw_script_error(id_from, 'Unmatched "(" parenthesis'); end if; set id_end_variables_definition := id_end_expression; - + set id_from := id_from + 1; -- Do we have anything in parenthesis at all? Or empty function like "function f()"? call _skip_spaces(id_from, id_end_variables_definition); @@ -53,7 +58,7 @@ main_body: begin -- And we do not actually declare the variables at this stage. -- //LEGACY -- do not uncomment// call _declare_local_variables(id_from, id_to, id_end_variables_definition, depth, _implode_nospace_array(variables_array_id)); end if; - + set variables_declaration_id := id_from; set consumed_to_id := id_end_expression; end; diff --git a/routines/script/functions/_expect_function_exists.sql b/routines/script/functions/_expect_function_exists.sql index ae3ca2e..415d33f 100644 --- a/routines/script/functions/_expect_function_exists.sql +++ b/routines/script/functions/_expect_function_exists.sql @@ -9,7 +9,7 @@ drop procedure if exists _expect_function_exists // create procedure _expect_function_exists( in id_from int unsigned, in check_function_name text charset utf8 -) +) comment 'Expects existence of function by name' language SQL deterministic @@ -19,7 +19,8 @@ sql security invoker main_body: begin declare function_found tinyint unsigned default FALSE; - select count(*) from _qs_functions where function_name = check_function_name into function_found; + select count(*) from _qs_functions where function_name = check_function_name into @_function_found; + set function_found=@_function_found; if not function_found then call _throw_script_error(id_from, CONCAT('Cannot find function: ', check_function_name)); diff --git a/routines/script/split/_split_assign_initial_range_start_variables.sql b/routines/script/split/_split_assign_initial_range_start_variables.sql index 04ba5ac..98e005a 100644 --- a/routines/script/split/_split_assign_initial_range_start_variables.sql +++ b/routines/script/split/_split_assign_initial_range_start_variables.sql @@ -1,11 +1,11 @@ --- --- --- +-- +-- +-- DELIMITER $$ DROP PROCEDURE IF EXISTS _split_assign_initial_range_start_variables $$ -CREATE PROCEDURE _split_assign_initial_range_start_variables() +CREATE PROCEDURE _split_assign_initial_range_start_variables() READS SQL DATA SQL SECURITY INVOKER COMMENT '' @@ -13,16 +13,17 @@ COMMENT '' begin declare queries text default NULL; - select + select GROUP_CONCAT( 'set ', range_start_variable_name, ' := ', min_variable_name, ';' separator '' ) from _split_column_names_table - into queries; - - call exec(queries); + into @_queries; + set queries=@_queries; + call exec(queries); + set @_split_column_variable_range_end_1 := NULL; end $$ diff --git a/routines/script/split/_split_assign_min_max_variables.sql b/routines/script/split/_split_assign_min_max_variables.sql index a461c4e..a55aefa 100644 --- a/routines/script/split/_split_assign_min_max_variables.sql +++ b/routines/script/split/_split_assign_min_max_variables.sql @@ -1,17 +1,17 @@ --- --- --- +-- +-- +-- DELIMITER $$ DROP PROCEDURE IF EXISTS _split_assign_min_max_variables $$ CREATE PROCEDURE _split_assign_min_max_variables( id_from int unsigned, - split_table_schema varchar(128), + split_table_schema varchar(128), split_table_name varchar(128), split_options varchar(2048) charset utf8, out is_empty_range tinyint unsigned - ) + ) READS SQL DATA SQL SECURITY INVOKER COMMENT '' @@ -27,12 +27,12 @@ begin declare columns_count tinyint unsigned default _split_get_columns_count(); declare start_values text default get_option(split_options, 'start'); declare stop_values text default get_option(split_options, 'stop'); - + set is_empty_range := false; set query := CONCAT( 'select ', column_names, ' from ', - mysql_qualify(split_table_schema), '.', mysql_qualify(split_table_name), + mysql_qualify(split_table_schema), '.', mysql_qualify(split_table_name), ' order by ', columns_order_ascending_clause, ' limit 1 ', ' into ', min_variables_names @@ -41,20 +41,21 @@ begin set query := CONCAT( 'select ', column_names, ' from ', - mysql_qualify(split_table_schema), '.', mysql_qualify(split_table_name), + mysql_qualify(split_table_schema), '.', mysql_qualify(split_table_name), ' order by ', columns_order_descending_clause, ' limit 1 ', ' into ', max_variables_names ); call exec_single(query); - + if start_values is not null then if columns_count = get_num_tokens(start_values, ',') then - select + select group_concat('set ', min_variable_name, ' := ', QUOTE(split_token(start_values, ',', column_order)), ';' order by column_order separator '') from _split_column_names_table - into query; + into @_query; + set query=@_query; call exec(query); set manual_min_max_params_used := true; else @@ -63,11 +64,12 @@ begin end if; if stop_values is not null then if columns_count = get_num_tokens(stop_values, ',') then - select + select group_concat('set ', max_variable_name, ' := ', QUOTE(split_token(stop_values, ',', column_order)), ';' order by column_order separator '') from _split_column_names_table - into query; + into @_query; + set query=@_query; call exec(query); set manual_min_max_params_used := true; else @@ -78,25 +80,28 @@ begin -- Due to manual intervention, we need to verify boundaries. -- We know for certain there is one column in splitting key (due to above checks) - select + set @_query=null; + select CONCAT( 'SELECT (', GROUP_CONCAT(min_variable_name order by column_order), ') > (', GROUP_CONCAT(max_variable_name order by column_order), ') INTO @_split_is_empty_range_result' ) from _split_column_names_table - into query; + into @_query; + set query=@_query; call exec_single(query); - + if @_split_is_empty_range_result then set is_empty_range := true; end if; - + end if; -- Check if range is empty - select + set @_query=null; + select CONCAT( 'SELECT (', GROUP_CONCAT( @@ -106,14 +111,15 @@ begin ') INTO @_split_is_empty_range_result' ) from _split_column_names_table - into query; + into @_query; + set query=@_query; call exec_single(query); if @_split_is_empty_range_result then set is_empty_range := true; end if; - + set @_query_script_split_min := TRIM(TRAILING ',' FROM CONCAT_WS(',', IF(columns_count >= 1, QUOTE((SELECT @_split_column_variable_min_1)), ''), IF(columns_count >= 2, QUOTE((SELECT @_split_column_variable_min_2)), ''), @@ -136,7 +142,7 @@ begin IF(columns_count >= 8, QUOTE((SELECT @_split_column_variable_max_8)), ''), IF(columns_count >= 9, QUOTE((SELECT @_split_column_variable_max_9)), '') )); - + end $$ DELIMITER ; diff --git a/routines/script/split/_split_assign_next_range_start_variables.sql b/routines/script/split/_split_assign_next_range_start_variables.sql index 4c5e820..0c0677e 100644 --- a/routines/script/split/_split_assign_next_range_start_variables.sql +++ b/routines/script/split/_split_assign_next_range_start_variables.sql @@ -1,11 +1,11 @@ --- --- --- +-- +-- +-- DELIMITER $$ DROP PROCEDURE IF EXISTS _split_assign_next_range_start_variables $$ -CREATE PROCEDURE _split_assign_next_range_start_variables() +CREATE PROCEDURE _split_assign_next_range_start_variables() READS SQL DATA SQL SECURITY INVOKER COMMENT '' @@ -13,13 +13,14 @@ COMMENT '' begin declare queries text default NULL; - select + select GROUP_CONCAT( 'set ', range_start_variable_name, ' := ', range_end_variable_name, ';' separator '' ) from _split_column_names_table - into queries; + into @_queries; + set queries=@_queries; call exec(queries); end $$ diff --git a/routines/script/split/_split_deduce_columns.sql b/routines/script/split/_split_deduce_columns.sql index c92aba8..64aa39b 100644 --- a/routines/script/split/_split_deduce_columns.sql +++ b/routines/script/split/_split_deduce_columns.sql @@ -1,11 +1,11 @@ --- --- --- +-- +-- +-- DELIMITER $$ DROP PROCEDURE IF EXISTS _split_deduce_columns $$ -CREATE PROCEDURE _split_deduce_columns(split_table_schema varchar(128), split_table_name varchar(128), requested_index_name varchar(128)) +CREATE PROCEDURE _split_deduce_columns(split_table_schema varchar(128), split_table_name varchar(128), requested_index_name varchar(128)) MODIFIES SQL DATA SQL SECURITY INVOKER COMMENT 'split values by columns...' @@ -15,16 +15,18 @@ begin declare split_num_column tinyint unsigned; call _split_generate_dependency_tables(split_table_schema, split_table_name, requested_index_name); - - SELECT + + SELECT column_names, count_column_in_index, index_name - FROM - _split_candidate_keys_recommended - WHERE - table_schema = split_table_schema AND table_name = split_table_name - INTO split_column_names, split_num_column, @_query_script_split_index_name + FROM + _split_candidate_keys_recommended + WHERE + table_schema = split_table_schema AND table_name = split_table_name + INTO @_split_column_names, @_split_num_column, @_query_script_split_index_name ; - + set split_column_names=@_split_column_names; + set split_num_column=@_split_num_column; + call _split_cleanup_dependency_tables(); if (requested_index_name is not null) and ((requested_index_name = @_query_script_split_index_name) IS NOT TRUE) then @@ -51,16 +53,16 @@ begin CONCAT('@_split_column_variable_range_end_', n) from numbers - where + where n between 1 and split_num_column ; - + select group_concat(mysql_qualify(column_name) order by column_order) from _split_column_names_table into - @_query_script_split_columns; + @_query_script_split_columns; end $$ DELIMITER ; diff --git a/routines/script/split/_split_get_columns_comparison_clause.sql b/routines/script/split/_split_get_columns_comparison_clause.sql index f7e5b2d..1e27033 100644 --- a/routines/script/split/_split_get_columns_comparison_clause.sql +++ b/routines/script/split/_split_get_columns_comparison_clause.sql @@ -1,54 +1,56 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_columns_comparison_clause $$ CREATE function _split_get_columns_comparison_clause( - comparison_operator VARCHAR(3), - split_variable_type enum('range_start', 'range_end', 'max'), + comparison_operator VARCHAR(3), + split_variable_type enum('range_start', 'range_end', 'max'), comparison_includes_equals TINYINT UNSIGNED, - num_split_columns TINYINT UNSIGNED) + num_split_columns TINYINT UNSIGNED) returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - + select group_concat('(', partial_comparison, ')' order by n separator ' OR ') as comparison from ( - select + select n, group_concat('(', column_name, ' ', if(is_last, comparison_operator, '='), ' ', variable_name, ')' order by column_order separator ' AND ') as partial_comparison from ( - select + select n, CONCAT(mysql_qualify(split_table_name), '.', mysql_qualify(column_name)) AS column_name, case split_variable_type when 'range_start' then range_start_variable_name when 'range_end' then range_end_variable_name when 'max' then max_variable_name end as variable_name, - _split_column_names_table.column_order, _split_column_names_table.column_order = n as is_last - from - numbers, _split_column_names_table - where - n between _split_column_names_table.column_order and num_split_columns + _split_column_names_table.column_order, _split_column_names_table.column_order = n as is_last + from + numbers, _split_column_names_table + where + n between _split_column_names_table.column_order and num_split_columns order by n, _split_column_names_table.column_order ) s1 group by n ) s2 - into return_value + into @_return_value ; - + set return_value=@_return_value; + if comparison_includes_equals then + set @_return_value=null; select CONCAT( return_value, ' OR (', GROUP_CONCAT( - '(', CONCAT(mysql_qualify(split_table_name), '.', mysql_qualify(column_name)), ' = ', + '(', CONCAT(mysql_qualify(split_table_name), '.', mysql_qualify(column_name)), ' = ', case split_variable_type when 'range_start' then range_start_variable_name when 'range_end' then range_end_variable_name @@ -59,8 +61,9 @@ BEGIN ) from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; end if; set return_value := CONCAT('(', return_value, ')'); diff --git a/routines/script/split/_split_get_columns_count.sql b/routines/script/split/_split_get_columns_count.sql index 4761dd2..9049fe2 100644 --- a/routines/script/split/_split_get_columns_count.sql +++ b/routines/script/split/_split_get_columns_count.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_columns_count $$ -CREATE function _split_get_columns_count() +CREATE function _split_get_columns_count() returns TINYINT UNSIGNED DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TINYINT UNSIGNED; - - select + + select count(*) from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_columns_names.sql b/routines/script/split/_split_get_columns_names.sql index 741822f..d6a21b7 100644 --- a/routines/script/split/_split_get_columns_names.sql +++ b/routines/script/split/_split_get_columns_names.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_columns_names $$ -CREATE function _split_get_columns_names() +CREATE function _split_get_columns_names() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(column_name order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_columns_order_ascending_clause.sql b/routines/script/split/_split_get_columns_order_ascending_clause.sql index 05a3446..2eda9ff 100644 --- a/routines/script/split/_split_get_columns_order_ascending_clause.sql +++ b/routines/script/split/_split_get_columns_order_ascending_clause.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_columns_order_ascending_clause $$ -CREATE function _split_get_columns_order_ascending_clause() +CREATE function _split_get_columns_order_ascending_clause() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(column_name, ' ASC' order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_columns_order_descending_clause.sql b/routines/script/split/_split_get_columns_order_descending_clause.sql index e2e0446..97e73db 100644 --- a/routines/script/split/_split_get_columns_order_descending_clause.sql +++ b/routines/script/split/_split_get_columns_order_descending_clause.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_columns_order_descending_clause $$ -CREATE function _split_get_columns_order_descending_clause() +CREATE function _split_get_columns_order_descending_clause() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(column_name, ' DESC' order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_max_variables_names.sql b/routines/script/split/_split_get_max_variables_names.sql index 6055325..61cf34b 100644 --- a/routines/script/split/_split_get_max_variables_names.sql +++ b/routines/script/split/_split_get_max_variables_names.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_max_variables_names $$ -CREATE function _split_get_max_variables_names() +CREATE function _split_get_max_variables_names() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(max_variable_name order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_min_variables_names.sql b/routines/script/split/_split_get_min_variables_names.sql index 6535ac3..921aac4 100644 --- a/routines/script/split/_split_get_min_variables_names.sql +++ b/routines/script/split/_split_get_min_variables_names.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_min_variables_names $$ -CREATE function _split_get_min_variables_names() +CREATE function _split_get_min_variables_names() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(min_variable_name order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_range_end_variables_names.sql b/routines/script/split/_split_get_range_end_variables_names.sql index e005ecb..da9b545 100644 --- a/routines/script/split/_split_get_range_end_variables_names.sql +++ b/routines/script/split/_split_get_range_end_variables_names.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_range_end_variables_names $$ -CREATE function _split_get_range_end_variables_names() +CREATE function _split_get_range_end_variables_names() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(range_end_variable_name order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_get_range_start_variables_names.sql b/routines/script/split/_split_get_range_start_variables_names.sql index c64927e..c9256b9 100644 --- a/routines/script/split/_split_get_range_start_variables_names.sql +++ b/routines/script/split/_split_get_range_start_variables_names.sql @@ -1,24 +1,25 @@ --- --- +-- +-- DELIMITER $$ DROP function IF EXISTS _split_get_range_start_variables_names $$ -CREATE function _split_get_range_start_variables_names() +CREATE function _split_get_range_start_variables_names() returns TEXT CHARSET utf8 DETERMINISTIC READS SQL DATA SQL SECURITY INVOKER COMMENT '' -BEGIN +BEGIN declare return_value TEXT CHARSET utf8; - - select + + select group_concat(range_start_variable_name order by column_order separator ', ') from _split_column_names_table - into return_value + into @_return_value ; + set return_value=@_return_value; return return_value; END $$ diff --git a/routines/script/split/_split_init_variables.sql b/routines/script/split/_split_init_variables.sql index 9519eaf..a156c68 100644 --- a/routines/script/split/_split_init_variables.sql +++ b/routines/script/split/_split_init_variables.sql @@ -1,11 +1,11 @@ --- --- --- +-- +-- +-- DELIMITER $$ DROP PROCEDURE IF EXISTS _split_init_variables $$ -CREATE PROCEDURE _split_init_variables() +CREATE PROCEDURE _split_init_variables() READS SQL DATA SQL SECURITY INVOKER COMMENT '' @@ -13,7 +13,7 @@ COMMENT '' begin declare queries text default NULL; - select + select GROUP_CONCAT( 'set ', min_variable_name, ' := NULL; ', 'set ', max_variable_name, ' := NULL; ', @@ -22,8 +22,9 @@ begin separator '' ) from _split_column_names_table - into queries; - + into @_queries; + set queries=@_queries; + call exec(queries); end $$ diff --git a/routines/script/split/analyze/_get_split_query_table_definitions_clause.sql b/routines/script/split/analyze/_get_split_query_table_definitions_clause.sql index 452a669..2c919d3 100644 --- a/routines/script/split/analyze/_get_split_query_table_definitions_clause.sql +++ b/routines/script/split/analyze/_get_split_query_table_definitions_clause.sql @@ -26,71 +26,79 @@ main_body: begin declare starting_id int unsigned; declare terminating_id int unsigned; declare following_select_id int unsigned; - + set table_definitions_found := false; set table_definitions_id_from := null; set table_definitions_id_to := null; - + if split_query_type = 'unsupported' then leave main_body; end if; - - select level from _sql_tokens where id = id_from into statement_level; + + set @_statement_level=null; + select level from _sql_tokens where id = id_from into @_statement_level; + set statement_level=@_statement_level; if split_query_type = 'update' then - select MIN(id) from _sql_tokens where (id between id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'set' into terminating_id; + select MIN(id) from _sql_tokens where (id between id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'set' into @_terminating_id; + set terminating_id=@_terminating_id; if terminating_id is not null then set table_definitions_found := true; set table_definitions_id_from := id_from + 1; set table_definitions_id_to := terminating_id - 1; end if; - leave main_body; + leave main_body; end if; if split_query_type = 'delete' then -- find FROM - select MIN(id) from _sql_tokens where (id between id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'from' into starting_id; + select MIN(id) from _sql_tokens where (id between id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'from' into @_starting_id; + set starting_id=@_starting_id; if starting_id is not null then set table_definitions_found := true; set table_definitions_id_from := starting_id + 1; -- But if there's USING, then override: - select MIN(id) from _sql_tokens where (id between table_definitions_id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'using' into starting_id; + select MIN(id) from _sql_tokens where (id between table_definitions_id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'using' into @_starting_id; + set starting_id=@_starting_id; if starting_id is not null then set table_definitions_id_from := starting_id + 1; end if; -- now find the terminating token: WHERE, ORDER or LIMIT (or end of line) - select MIN(id) from _sql_tokens where (id between table_definitions_id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) in ('where', 'order', 'limit') into terminating_id; + select MIN(id) from _sql_tokens where (id between table_definitions_id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) in ('where', 'order', 'limit') into @_terminating_id; + set terminating_id=@_terminating_id; if terminating_id is not null then set table_definitions_id_to := terminating_id - 1; else set table_definitions_id_to := id_to; end if; end if; - leave main_body; + leave main_body; end if; if split_query_type in ('insert_select', 'replace_select') then - -- We know for sure the 'INSERT' or 'REPLACE' are followed by a 'SELECT'. - -- It just so happens that there's nothing special about it: we can parse the query + -- We know for sure the 'INSERT' or 'REPLACE' are followed by a 'SELECT'. + -- It just so happens that there's nothing special about it: we can parse the query -- as if it were a SELECT query: we just look for the FROM clause. set split_query_type := 'select'; end if; if split_query_type = 'select' then -- find FROM - select MIN(id) from _sql_tokens where (id between id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'from' into starting_id; + select MIN(id) from _sql_tokens where (id between id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) = 'from' into @_starting_id; + set starting_id=@_starting_id; if starting_id is not null then set table_definitions_found := true; set table_definitions_id_from := starting_id + 1; -- now find the terminating token: WHERE, ORDER or LIMIT (or end of line) - select MIN(id) from _sql_tokens where (id between table_definitions_id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) in ('partition', 'where', 'group', 'having', 'order', 'limit', 'procedure', 'into', 'for', 'lock') into terminating_id; + select MIN(id) from _sql_tokens where (id between table_definitions_id_from and id_to) and level = statement_level and state = 'alpha' and LOWER(token) in ('partition', 'where', 'group', 'having', 'order', 'limit', 'procedure', 'into', 'for', 'lock') into @_terminating_id; + set terminating_id=@_terminating_id; if terminating_id is not null then set table_definitions_id_to := terminating_id - 1; else set table_definitions_id_to := id_to; end if; end if; - leave main_body; + leave main_body; end if; end; // diff --git a/routines/script/split/analyze/_get_split_query_type.sql b/routines/script/split/analyze/_get_split_query_type.sql index 8c438a5..7952cd2 100644 --- a/routines/script/split/analyze/_get_split_query_type.sql +++ b/routines/script/split/analyze/_get_split_query_type.sql @@ -22,17 +22,24 @@ sql security invoker main_body: begin declare statement_level int unsigned; declare statement_type tinytext charset utf8 default null; - + set split_query_type := 'unsupported'; set split_query_following_select_id := null; - + call _skip_spaces(id_from, id_to); - SELECT id, level, LOWER(token) FROM _sql_tokens WHERE id = id_from AND state = 'alpha' INTO split_query_id_from, statement_level, statement_type; - + set @_split_query_id_from=null, @_statement_level=null, @_statement_type=null; + SELECT id, level, LOWER(token) FROM _sql_tokens WHERE id = id_from AND state = 'alpha' INTO @_split_query_id_from, @_statement_level, @_statement_type; + set + split_query_id_from=@_split_query_id_from, + statement_level=@_statement_level, + statement_type=@_statement_type + ; + if statement_type in ('insert', 'replace') then - SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND id <= id_to AND level = statement_level AND state = 'alpha' AND LOWER(token) = 'select' INTO split_query_following_select_id; + SELECT MIN(id) FROM _sql_tokens WHERE id > id_from AND id <= id_to AND level = statement_level AND state = 'alpha' AND LOWER(token) = 'select' INTO @_split_query_following_select_id; + set split_query_following_select_id=@_split_query_following_select_id; end if; - + if statement_type = 'delete' then set split_query_type := 'delete'; elseif statement_type = 'update' then diff --git a/routines/script/split/analyze/_get_split_single_table_from_table_definitions.sql b/routines/script/split/analyze/_get_split_single_table_from_table_definitions.sql index bf6b631..31f5287 100644 --- a/routines/script/split/analyze/_get_split_single_table_from_table_definitions.sql +++ b/routines/script/split/analyze/_get_split_single_table_from_table_definitions.sql @@ -10,7 +10,7 @@ create procedure _get_split_single_table_from_table_definitions ( in id_from int unsigned, in id_to int unsigned, out tables_found enum ('none', 'single', 'multi'), - out table_schema varchar(80) charset utf8, + out table_schema varchar(80) charset utf8, out table_name varchar(80) charset utf8 ) comment 'Get table_schema, table_name from table definitions clause' @@ -20,29 +20,32 @@ reads sql data sql security invoker main_body: begin declare statement_level int unsigned; - declare multi_table_indicator_id int unsigned; + declare multi_table_indicator_id int unsigned; declare tokens_array_id int unsigned; declare peek_match_to int unsigned; - + set table_schema := null; set table_name := null; set tables_found := 'none'; - - select level from _sql_tokens where id = id_from into statement_level; + + set @_statement_level=null; + select level from _sql_tokens where id = id_from into @_statement_level; + set statement_level=@_statement_level; -- Check for multiple tables indicator: a JOIN, a STRAIGHT_JOIN, a comma, -- parenthesis (may indicate subquery, a USE INDEX, ON, USING) -- Oh, yes -- index hints not allwed here. - select MIN(id) from _sql_tokens where - (id between id_from and id_to) + select MIN(id) from _sql_tokens where + (id between id_from and id_to) and ( ((state = 'comma') and (level = statement_level)) - or + or ((state = 'alpha') and (LOWER(token) in ('join', 'straight_join')) and (level = statement_level)) - or + or ((state = 'left parenthesis') and (level = statement_level + 1)) ) - into multi_table_indicator_id; - + into @_multi_table_indicator_id; + set multi_table_indicator_id=@_multi_table_indicator_id; + if multi_table_indicator_id is not null then set tables_found := 'multi'; leave main_body; @@ -58,7 +61,7 @@ main_body: begin call _skip_tokens_and_spaces(id_from, id_to, 'ignore,low_priority'); call _peek_states_list(id_from, id_to, 'alpha|alphanum|quoted identifier|expanded query_script variable,dot,alpha|alphanum|quoted identifier|expanded query_script variable', false, false, true, tokens_array_id, peek_match_to); if peek_match_to > 0 then - call _get_array_element(tokens_array_id, '1', table_schema); + call _get_array_element(tokens_array_id, '1', table_schema); call _get_array_element(tokens_array_id, '3', table_name); set table_schema := unquote(table_schema); set table_name := unquote(table_name); diff --git a/routines/script/split/analyze/_inject_split_where_token.sql b/routines/script/split/analyze/_inject_split_where_token.sql index 4d6b422..8d1c658 100644 --- a/routines/script/split/analyze/_inject_split_where_token.sql +++ b/routines/script/split/analyze/_inject_split_where_token.sql @@ -20,32 +20,35 @@ reads sql data sql security invoker main_body: begin declare statement_level int unsigned; - declare id_where_clause int unsigned default NULL; - declare id_where_clause_end int unsigned default NULL; + declare id_where_clause int unsigned default NULL; + declare id_where_clause_end int unsigned default NULL; declare id_end_split_table_declaration int unsigned default NULL; declare query_part_prefix text charset utf8 default ''; declare query_part_where_clause text charset utf8 default ''; declare query_part_suffix text charset utf8 default ''; - declare split_query_type varchar(32) charset ascii; - declare split_query_id_from int unsigned; + declare split_query_type varchar(32) charset ascii; + declare split_query_id_from int unsigned; declare split_query_following_select_id int unsigned; - + call _skip_spaces(id_from, id_to); - SELECT level FROM _sql_tokens WHERE id = id_from INTO statement_level; - + set @_statement_level=null; + SELECT level FROM _sql_tokens WHERE id = id_from INTO @_statement_level; + set statement_level=@_statement_level; + -- Analyze query type call _get_split_query_type(id_from, id_to, split_query_type, split_query_id_from, split_query_following_select_id); - + if split_query_type = 'unsupported' then call _throw_script_error(id_from, 'split(): unsupported query type'); end if; - SELECT - MIN(id) FROM _sql_tokens - WHERE - level = statement_level AND state = 'alpha' and LOWER(token) = 'where' + SELECT + MIN(id) FROM _sql_tokens + WHERE + level = statement_level AND state = 'alpha' and LOWER(token) = 'where' AND id between id_from and id_to - INTO id_where_clause; + INTO @_id_where_clause; + set id_where_clause=@_id_where_clause; if id_where_clause is NULL then -- No "WHERE" clause. -- Attempt to find a clause which appears after the WHERE clause @@ -53,13 +56,14 @@ main_body: begin -- "INTO" is such a pain: is appears both in "INSERT INTO ... SELECT" (irrelevant to our injection) -- as well as in "SELECT ... INTO ..." (relevant to our injection) -- There's a lot of fuss to make sure to stop at the right "INTO". - SELECT - MIN(id) FROM _sql_tokens - WHERE - level = statement_level - AND state = 'alpha' and LOWER(token) IN ('group', 'having', 'order', 'limit', 'into') + SELECT + MIN(id) FROM _sql_tokens + WHERE + level = statement_level + AND state = 'alpha' and LOWER(token) IN ('group', 'having', 'order', 'limit', 'into') AND id between GREATEST(id_from, split_query_id_from, IFNULL(split_query_following_select_id, split_query_id_from)) and id_to - INTO id_where_clause_end; + INTO @_id_where_clause_end; + set id_where_clause_end=@_id_where_clause_end; if id_where_clause_end is NULL then -- No "WHERE", no following clause... Just invent a new "WHERE" clause... call _expand_statement_variables(id_from, id_to, query_part_prefix, @common_schema_dummy, should_execute_statement); @@ -77,16 +81,17 @@ main_body: begin -- "WHERE" clause found. call _expand_statement_variables(id_from, id_where_clause, query_part_prefix, @common_schema_dummy, should_execute_statement); -- Search for end of "WHERE" clause - SELECT - MIN(id) FROM _sql_tokens - WHERE - level = statement_level - AND state = 'alpha' and LOWER(token) IN ('group', 'having', 'order', 'limit', 'into') + SELECT + MIN(id) FROM _sql_tokens + WHERE + level = statement_level + AND state = 'alpha' and LOWER(token) IN ('group', 'having', 'order', 'limit', 'into') AND id between id_from and id_to AND id > id_where_clause - INTO id_where_clause_end; + INTO @_id_where_clause_end; + set id_where_clause_end=@_id_where_clause_end; if id_where_clause_end is NULL then - -- Nothing after the "WHERE" clause. So the "WHERE" clause + -- Nothing after the "WHERE" clause. So the "WHERE" clause -- terminates at id_to call _expand_statement_variables(id_where_clause + 1, id_to, query_part_where_clause, @common_schema_dummy, should_execute_statement); else diff --git a/routines/script/states/_consume_if_exists.sql b/routines/script/states/_consume_if_exists.sql index 36186d9..5387905 100644 --- a/routines/script/states/_consume_if_exists.sql +++ b/routines/script/states/_consume_if_exists.sql @@ -14,7 +14,7 @@ create procedure _consume_if_exists( in expected_states text charset utf8, out token_has_matched tinyint unsigned, out matched_token text charset utf8 -) +) comment 'Consumes token or state if indeed exists' language SQL deterministic @@ -24,7 +24,10 @@ sql security invoker main_body: begin call _skip_spaces(id_from, id_to); set token_has_matched := FALSE; - SELECT token, ((token = expected_token) OR FIND_IN_SET(state, REPLACE(expected_states, '|', ','))) IS TRUE FROM _sql_tokens WHERE id = id_from INTO matched_token, token_has_matched; + set @_matched_token=null, @_token_has_matched=FALSE; + SELECT token, ((token = expected_token) OR FIND_IN_SET(state, REPLACE(expected_states, '|', ','))) IS TRUE FROM _sql_tokens WHERE id = id_from INTO @_matched_token, @_token_has_matched; + set matched_token=@_matched_token; + set token_has_matched=@_token_has_matched; if token_has_matched then set consumed_to_id = id_from; end if; diff --git a/routines/script/states/_match_states.sql b/routines/script/states/_match_states.sql index 6c72d91..0896868 100644 --- a/routines/script/states/_match_states.sql +++ b/routines/script/states/_match_states.sql @@ -1,5 +1,5 @@ -- --- Given a state (or optional states), expect a dynamic length comma +-- Given a state (or optional states), expect a dynamic length comma -- delimited list where each element is given state(s). -- @@ -21,7 +21,7 @@ create procedure _match_states( out tokens_array_id VARCHAR(16) charset ascii, out single_matched_token text charset utf8, out consumed_to_id int unsigned -) +) comment 'Expects a state or raises error' language SQL deterministic @@ -34,7 +34,7 @@ main_body: begin declare states_index int unsigned; declare repeat_index int unsigned; declare expected_states text charset utf8; - + if return_tokens_array_id then call _create_array(tokens_array_id); end if; @@ -43,7 +43,7 @@ main_body: begin if num_states = 0 then call _throw_script_error(id_from, 'Internal error: num_states = 0 in _match_states'); end if; - + -- repeat_count = 0 means undefined length, dynamic. set states_have_matched := true; set repeat_index := 1; @@ -62,7 +62,11 @@ main_body: begin end if; set expected_states := split_token(expected_states_list, ',', states_index); - select token, FIND_IN_SET(state, REPLACE(expected_states, '|', ',')) is true from _sql_tokens where id = id_from into single_matched_token, state_has_matched; + set @_state_has_matched=false; + set @_single_matched_token=null; + select token, FIND_IN_SET(state, REPLACE(expected_states, '|', ',')) is true from _sql_tokens where id = id_from into @_single_matched_token, @_state_has_matched; + set single_matched_token=@_single_matched_token; + set state_has_matched=@_state_has_matched; if state_has_matched then set consumed_to_id := id_from; if return_tokens_array_id then @@ -73,18 +77,20 @@ main_body: begin leave repeat_loop; end if; set id_from := id_from + 1; - + set states_index := states_index + 1; end while; -- End reading single-occurence of expected states. -- We now expect delimiters, if appliccable (NULL delimiter means no delimiter expected) if repeat_delimiter_state != 'whitespace' then -- If expected delimiter is whitespace, well, we want to consume it, - -- not skip it... + -- not skip it... call _skip_spaces(id_from, id_to); end if; if repeat_delimiter_state is not null then - select token, (state = repeat_delimiter_state) from _sql_tokens where id = id_from into @_common_schema_dummy, state_has_matched; + set @_state_has_matched=false; + select token, (state = repeat_delimiter_state) from _sql_tokens where id = id_from into @_common_schema_dummy, @_state_has_matched; + set state_has_matched=@_state_has_matched; if not state_has_matched then -- Could not find dilimiter. -- This is fine for last repeat-step, or when there is @@ -98,7 +104,7 @@ main_body: begin set id_from := id_from + 1; end if; -- Phew, got here: this means a delimiter is matched. - set repeat_index := repeat_index + 1; + set repeat_index := repeat_index + 1; end while; if states_have_matched then @@ -107,7 +113,7 @@ main_body: begin -- don't care about the rest leave main_body; end if; - + -- Do not allow trailing states: expect nothing more but spaces or statement delimiter call _skip_spaces(id_from, id_to); call _skip_end_of_statement(id_from, id_to); @@ -115,7 +121,7 @@ main_body: begin set states_have_matched := false; end if; end if; - + if not states_have_matched then -- This entire routine fails: there is no match if throw_on_mismatch then diff --git a/routines/script/states/_skip_empty_spaces.sql b/routines/script/states/_skip_empty_spaces.sql index 4d3f5aa..6d7c45c 100644 --- a/routines/script/states/_skip_empty_spaces.sql +++ b/routines/script/states/_skip_empty_spaces.sql @@ -18,10 +18,11 @@ deterministic reads sql data sql security invoker main_body: begin - select min(id) from _sql_tokens - where id >= id_from and id <= id_to - and (state, CHAR_LENGTH(token)) != ('whitespace', 0) - into id_from; + select min(id) from _sql_tokens + where id >= id_from and id <= id_to + and (state, CHAR_LENGTH(token)) != ('whitespace', 0) + into @_id_from; + set id_from=@_id_from; if id_from is null then set id_from := id_to + 1; end if; diff --git a/routines/script/states/_skip_states.sql b/routines/script/states/_skip_states.sql index c5023d1..9d8c22a 100644 --- a/routines/script/states/_skip_states.sql +++ b/routines/script/states/_skip_states.sql @@ -20,11 +20,12 @@ sql security invoker main_body: begin set states_list := IFNULL(states_list, ''); set tokens_list := LOWER(IFNULL(tokens_list, '')); - select min(id) from _sql_tokens - where id >= id_from and id <= id_to - and FIND_IN_SET(state, states_list) = 0 - and FIND_IN_SET(LOWER(token), tokens_list) = 0 - into id_from; + select min(id) from _sql_tokens + where id >= id_from and id <= id_to + and FIND_IN_SET(state, states_list) = 0 + and FIND_IN_SET(LOWER(token), tokens_list) = 0 + into @_id_from; + set id_from=@_id_from; if id_from is null then set id_from := id_to + 1; end if; diff --git a/routines/script/states/_validate_statement_end.sql b/routines/script/states/_validate_statement_end.sql index 276fafb..dc26458 100644 --- a/routines/script/states/_validate_statement_end.sql +++ b/routines/script/states/_validate_statement_end.sql @@ -1,5 +1,5 @@ -- --- Expects and validates that statement ends with delimiter or end of block, returning +-- Expects and validates that statement ends with delimiter or end of block, returning -- position of end of statement -- @@ -12,7 +12,7 @@ create procedure _validate_statement_end( in id_to int unsigned, out id_end_statement int unsigned, out statement_delimiter_found tinyint unsigned -) +) comment 'Validates delimiter or end of block' language SQL deterministic @@ -21,14 +21,17 @@ sql security invoker main_body: begin declare state_end_statement text charset utf8 default NULL; - + set id_end_statement := NULL; -- id_to limits scope of this statement until end of block or end of script. -- it is possible that a new block starts within these bounds, or multiple statements appear, or any combination of the above. - SELECT id, state FROM _sql_tokens WHERE id > id_from AND id <= id_to AND state IN ('statement delimiter', 'left braces') ORDER BY id ASC LIMIT 1 INTO id_end_statement, state_end_statement; + set @_id_end_statement=null, @_state_end_statement=null; + SELECT id, state FROM _sql_tokens WHERE id > id_from AND id <= id_to AND state IN ('statement delimiter', 'left braces') ORDER BY id ASC LIMIT 1 INTO @_id_end_statement, @_state_end_statement; + set id_end_statement=@_id_end_statement; + set state_end_statement=@_state_end_statement; if state_end_statement = 'left braces' then call _throw_script_error(id_from, 'Missing '';'' statement delimiter'); - end if; + end if; if id_end_statement IS NULL then -- Last query in script or block is allowed not to be terminated by ';' set id_end_statement := id_to; diff --git a/routines/script/variables/_assign_input_local_variables.sql b/routines/script/variables/_assign_input_local_variables.sql index 47bc68a..0c01619 100644 --- a/routines/script/variables/_assign_input_local_variables.sql +++ b/routines/script/variables/_assign_input_local_variables.sql @@ -21,24 +21,26 @@ main_body: begin declare local_variable varchar(65) charset ascii; declare user_defined_variable_name varchar(65) charset ascii; declare reset_query text charset ascii; - + call _get_array_size(variables_array_id, num_variables); set variable_index := 1; while variable_index <= num_variables do call _get_array_element(variables_array_id, variable_index, local_variable); - SELECT - mapped_user_defined_variable_name - FROM - _qs_variables - WHERE + set @_user_defined_variable_name=null; + SELECT + mapped_user_defined_variable_name + FROM + _qs_variables + WHERE variable_name = local_variable and (function_scope = _get_current_variables_function_scope()) - INTO - user_defined_variable_name; - + INTO + @_user_defined_variable_name; + set user_defined_variable_name=@_user_defined_variable_name; + set reset_query := CONCAT('SET ', user_defined_variable_name, ' := @_query_script_input_col', variable_index); call exec_single(reset_query); - + set variable_index := variable_index + 1; end while; end; diff --git a/routines/script/variables/_declare_and_assign_local_variable.sql b/routines/script/variables/_declare_and_assign_local_variable.sql index 8ca7bbe..ff490c9 100644 --- a/routines/script/variables/_declare_and_assign_local_variable.sql +++ b/routines/script/variables/_declare_and_assign_local_variable.sql @@ -27,35 +27,38 @@ main_body: begin declare set_expression text charset utf8; declare set_statement text charset utf8; declare declaration_is_new tinyint unsigned default 0; - + call _expect_state(statement_id_from, id_to, 'query_script variable', true, @_common_schema_dummy, local_variable); - SELECT - (COUNT(*) = 0) - FROM - _qs_variables - WHERE + SELECT + (COUNT(*) = 0) + FROM + _qs_variables + WHERE declaration_id = id_from and (function_scope = _get_current_variables_function_scope()) - INTO - declaration_is_new; + INTO + @_declaration_is_new; + set declaration_is_new=@_declaration_is_new; if declaration_is_new then set user_defined_variable_name := CONCAT('@__qs_local_var_', session_unique_id()); call _declare_local_variable(id_from, statement_id_to, id_to, depth, local_variable, user_defined_variable_name, TRUE); end if; - + if should_execute_statement then call _expand_statement_variables(assign_id+1, statement_id_to, set_expression, @_common_schema_dummy, should_execute_statement); - - select - CONCAT('SET ', mapped_user_defined_variable_name, ' := ', set_expression) - from - _qs_variables - where - variable_name = local_variable + + set @_set_statement=null; + select + CONCAT('SET ', mapped_user_defined_variable_name, ' := ', set_expression) + from + _qs_variables + where + variable_name = local_variable and declaration_depth = depth and (function_scope = _get_current_variables_function_scope()) - into set_statement; + into @_set_statement; + set set_statement=@_set_statement; call exec(set_statement); end if; end; diff --git a/routines/script/variables/_declare_local_variable.sql b/routines/script/variables/_declare_local_variable.sql index 4f98bc0..400591b 100644 --- a/routines/script/variables/_declare_local_variable.sql +++ b/routines/script/variables/_declare_local_variable.sql @@ -24,22 +24,16 @@ sql security invoker main_body: begin -- TODO: this makes the statement "var $e, $e;" valid, since both variables share same declaration id. -- Remove variables with same name as given variable, and which are out of scope: - delete - from - _qs_variables - WHERE - variable_name = local_variable + delete + from + _qs_variables + WHERE + variable_name = local_variable and ((scope_end_id < id_variable_declaration) or (declaration_id >= id_variable_declaration)) and (function_scope = _get_current_variables_function_scope()) ; - -- declare overlapping_variable_exists tinyint unsigned; - -- select (count(*) > 0) from _qs_variables where variable_name = local_variable and id_variable_declaration between declaration_id and scope_end_id into overlapping_variable_exists; - -- if overlapping_variable_exists and throw_when_exists then - -- call _throw_script_error(id_from, CONCAT('Duplicate local variable: ', local_variable)); - -- end if; - - INSERT IGNORE INTO _qs_variables (server_id, session_id, function_scope, variable_name, mapped_user_defined_variable_name, declaration_depth, declaration_id, scope_end_id) + INSERT IGNORE INTO _qs_variables (server_id, session_id, function_scope, variable_name, mapped_user_defined_variable_name, declaration_depth, declaration_id, scope_end_id) VALUES (_get_server_id(), CONNECTION_ID(), _get_current_variables_function_scope(), local_variable, user_defined_variable_name, depth, id_variable_declaration, id_to); if ROW_COUNT() = 0 and throw_when_exists then call _throw_script_error(id_variable_declaration, CONCAT('Duplicate local variable: ', local_variable)); diff --git a/routines/script/variables/_declare_local_variables.sql b/routines/script/variables/_declare_local_variables.sql index ee42c3b..51211a7 100644 --- a/routines/script/variables/_declare_local_variables.sql +++ b/routines/script/variables/_declare_local_variables.sql @@ -25,31 +25,32 @@ main_body: begin declare local_variable varchar(65) charset ascii; declare user_defined_variable_name varchar(65) charset ascii; declare declaration_is_new tinyint unsigned default 0; - - SELECT - (COUNT(*) = 0) - FROM - _qs_variables - WHERE + + SELECT + (COUNT(*) = 0) + FROM + _qs_variables + WHERE declaration_id = id_from and (function_scope = _get_current_variables_function_scope()) INTO - declaration_is_new; + @_declaration_is_new; + set declaration_is_new=@_declaration_is_new; if not declaration_is_new then -- Apparently there is a loop, since this id has already been visited and the variables in this id have already been declared. - -- There is no need to do anything. The previous end-of-the-loop caused the mapped user defined variables to be reset to NULL. + -- There is no need to do anything. The previous end-of-the-loop caused the mapped user defined variables to be reset to NULL. leave main_body; end if; - + -- Start declaration set num_variables := get_num_tokens(imploded_variables, ','); set variable_index := 1; while variable_index <= num_variables do set local_variable := split_token(imploded_variables, ',', variable_index); set user_defined_variable_name := CONCAT('@__qs_local_var_', session_unique_id()); - + call _declare_local_variable(id_from, statement_id_to, id_to, depth, local_variable, user_defined_variable_name, TRUE); - + set variable_index := variable_index + 1; end while; end; diff --git a/routines/script/variables/_expand_single_variable.sql b/routines/script/variables/_expand_single_variable.sql index f766092..b1f4b3d 100644 --- a/routines/script/variables/_expand_single_variable.sql +++ b/routines/script/variables/_expand_single_variable.sql @@ -20,38 +20,39 @@ sql security invoker main_body: begin declare expanded_variable_name TEXT CHARSET utf8; - + set expanded_variable_name := _extract_expanded_query_script_variable_name(variable_token); if expanded_variable_name is null then -- Token is not expanded variable... return as it leave main_body; end if; - + -- Token is expanded variable. Try to match it against current from->to scope. if not should_execute_statement then leave main_body; end if; - + call _take_local_variables_snapshot(expanded_variable_name); - - SELECT + + SELECT MIN(_qs_variables.value_snapshot) - FROM - _sql_tokens + FROM + _sql_tokens LEFT JOIN _qs_variables ON ( /* Try to match an expanded query script variable */ (state = 'expanded query_script variable' AND _extract_expanded_query_script_variable_name(token) = _qs_variables.variable_name and _qs_variables.function_scope IN ('', _get_current_variables_function_scope()) - and _qs_variables.variable_name = expanded_variable_name) /* expanded */ + and _qs_variables.variable_name = expanded_variable_name) /* expanded */ and (id_from between _qs_variables.declaration_id and _qs_variables.scope_end_id) ) - where - (id between id_from and id_to) + where + (id between id_from and id_to) order by function_scope desc limit 1 into - variable_token; + @_variable_token; + set variable_token=@_variable_token; end; // diff --git a/routines/script/variables/_expand_statement_variables.sql b/routines/script/variables/_expand_statement_variables.sql index b0fab97..dc96f45 100644 --- a/routines/script/variables/_expand_statement_variables.sql +++ b/routines/script/variables/_expand_statement_variables.sql @@ -21,35 +21,36 @@ sql security invoker main_body: begin declare expanded_variables TEXT CHARSET utf8; - - SELECT GROUP_CONCAT(DISTINCT _extract_expanded_query_script_variable_name(token)) from _sql_tokens where (id between id_from and id_to) and (state = 'expanded query_script variable') INTO expanded_variables; - set expanded_variables_found := (expanded_variables IS NOT NULL); + + SELECT GROUP_CONCAT(DISTINCT _extract_expanded_query_script_variable_name(token)) from _sql_tokens where (id between id_from and id_to) and (state = 'expanded query_script variable') INTO @_expanded_variables; + set expanded_variables=@_expanded_variables; + set expanded_variables_found := (expanded_variables IS NOT NULL); if expanded_variables_found and should_execute_statement then call _take_local_variables_snapshot(expanded_variables); end if; - SELECT + SELECT GROUP_CONCAT( case when _qs_variables_this_function.mapped_user_defined_variable_name IS NOT NULL then case - when state = 'expanded query_script variable' then _qs_variables_this_function.value_snapshot /* expanded */ + when state = 'expanded query_script variable' then _qs_variables_this_function.value_snapshot /* expanded */ else _qs_variables_this_function.mapped_user_defined_variable_name /* non-expanded */ end when _qs_variables_global.mapped_user_defined_variable_name IS NOT NULL then case - when state = 'expanded query_script variable' then _qs_variables_global.value_snapshot /* expanded */ + when state = 'expanded query_script variable' then _qs_variables_global.value_snapshot /* expanded */ else _qs_variables_global.mapped_user_defined_variable_name /* non-expanded */ end else token /* not a query script variable at all */ - end + end ORDER BY id ASC SEPARATOR '' - ) - FROM - _sql_tokens + ) + FROM + _sql_tokens LEFT JOIN _qs_variables AS _qs_variables_this_function ON ( /* Try to match a query script variable, or an expanded query script variable */ ( - (state = 'expanded query_script variable' AND _extract_expanded_query_script_variable_name(token) = _qs_variables_this_function.variable_name) /* expanded */ + (state = 'expanded query_script variable' AND _extract_expanded_query_script_variable_name(token) = _qs_variables_this_function.variable_name) /* expanded */ or (state = 'query_script variable' AND token = _qs_variables_this_function.variable_name) /* non-expanded */ ) and (id_from between _qs_variables_this_function.declaration_id and _qs_variables_this_function.scope_end_id) @@ -58,16 +59,17 @@ main_body: begin LEFT JOIN _qs_variables AS _qs_variables_global ON ( /* Try to match a query script variable, or an expanded query script variable */ ( - (state = 'expanded query_script variable' AND _extract_expanded_query_script_variable_name(token) = _qs_variables_global.variable_name) /* expanded */ + (state = 'expanded query_script variable' AND _extract_expanded_query_script_variable_name(token) = _qs_variables_global.variable_name) /* expanded */ or (state = 'query_script variable' AND token = _qs_variables_global.variable_name) /* non-expanded */ ) and (id_from between _qs_variables_global.declaration_id and _qs_variables_global.scope_end_id) and _qs_variables_global.function_scope = '' ) - where - (id between id_from and id_to) - into - expanded_statement; + where + (id between id_from and id_to) + into + @_expanded_statement; + set expanded_statement=@_expanded_statement; set expanded_statement := trim_wspace(expanded_statement); end; // diff --git a/routines/script/variables/_take_local_variables_snapshot.sql b/routines/script/variables/_take_local_variables_snapshot.sql index 7587664..8153e36 100644 --- a/routines/script/variables/_take_local_variables_snapshot.sql +++ b/routines/script/variables/_take_local_variables_snapshot.sql @@ -21,27 +21,29 @@ main_body: begin declare local_variable varchar(65) charset ascii; declare user_defined_variable_name varchar(65) charset ascii; declare snapshot_query text charset ascii; - + set num_variables := get_num_tokens(expanded_variables, ','); set variable_index := 1; while variable_index <= num_variables do set local_variable := split_token(expanded_variables, ',', variable_index); - SELECT - mapped_user_defined_variable_name - FROM - _qs_variables - WHERE + set @_user_defined_variable_name=null; + SELECT + mapped_user_defined_variable_name + FROM + _qs_variables + WHERE variable_name = local_variable and function_scope IN ('', _get_current_variables_function_scope()) ORDER BY function_scope DESC LIMIT 1 - INTO - user_defined_variable_name; - + INTO + @_user_defined_variable_name; + set user_defined_variable_name=@_user_defined_variable_name; + set snapshot_query := CONCAT('UPDATE _qs_variables SET value_snapshot = ', user_defined_variable_name, ' WHERE variable_name = ', QUOTE(local_variable)); call exec_single(snapshot_query); - + set variable_index := variable_index + 1; end while; end; diff --git a/tests/root/debugged_routines/01/description.txt b/tests/__legacy__/debugged_routines/01/description.txt similarity index 100% rename from tests/root/debugged_routines/01/description.txt rename to tests/__legacy__/debugged_routines/01/description.txt diff --git a/tests/root/debugged_routines/01/test.sql b/tests/__legacy__/debugged_routines/01/test.sql similarity index 100% rename from tests/root/debugged_routines/01/test.sql rename to tests/__legacy__/debugged_routines/01/test.sql diff --git a/tests/root/debugged_routines/02/description.txt b/tests/__legacy__/debugged_routines/02/description.txt similarity index 100% rename from tests/root/debugged_routines/02/description.txt rename to tests/__legacy__/debugged_routines/02/description.txt diff --git a/tests/root/debugged_routines/02/test.sql b/tests/__legacy__/debugged_routines/02/test.sql similarity index 100% rename from tests/root/debugged_routines/02/test.sql rename to tests/__legacy__/debugged_routines/02/test.sql diff --git a/tests/root/debugged_routines/pre.sql b/tests/__legacy__/debugged_routines/pre.sql similarity index 100% rename from tests/root/debugged_routines/pre.sql rename to tests/__legacy__/debugged_routines/pre.sql diff --git a/tests/root/rdebug_compile_routine/01/description.txt b/tests/__legacy__/rdebug_compile_routine/01/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/01/description.txt rename to tests/__legacy__/rdebug_compile_routine/01/description.txt diff --git a/tests/root/rdebug_compile_routine/01/test.sql b/tests/__legacy__/rdebug_compile_routine/01/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/01/test.sql rename to tests/__legacy__/rdebug_compile_routine/01/test.sql diff --git a/tests/root/rdebug_compile_routine/02/description.txt b/tests/__legacy__/rdebug_compile_routine/02/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/02/description.txt rename to tests/__legacy__/rdebug_compile_routine/02/description.txt diff --git a/tests/root/rdebug_compile_routine/02/test.sql b/tests/__legacy__/rdebug_compile_routine/02/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/02/test.sql rename to tests/__legacy__/rdebug_compile_routine/02/test.sql diff --git a/tests/root/rdebug_compile_routine/03/description.txt b/tests/__legacy__/rdebug_compile_routine/03/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/03/description.txt rename to tests/__legacy__/rdebug_compile_routine/03/description.txt diff --git a/tests/root/rdebug_compile_routine/03/test.sql b/tests/__legacy__/rdebug_compile_routine/03/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/03/test.sql rename to tests/__legacy__/rdebug_compile_routine/03/test.sql diff --git a/tests/root/rdebug_compile_routine/04/description.txt b/tests/__legacy__/rdebug_compile_routine/04/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/04/description.txt rename to tests/__legacy__/rdebug_compile_routine/04/description.txt diff --git a/tests/root/rdebug_compile_routine/04/test.sql b/tests/__legacy__/rdebug_compile_routine/04/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/04/test.sql rename to tests/__legacy__/rdebug_compile_routine/04/test.sql diff --git a/tests/root/rdebug_compile_routine/05/description.txt b/tests/__legacy__/rdebug_compile_routine/05/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/05/description.txt rename to tests/__legacy__/rdebug_compile_routine/05/description.txt diff --git a/tests/root/rdebug_compile_routine/05/test.sql b/tests/__legacy__/rdebug_compile_routine/05/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/05/test.sql rename to tests/__legacy__/rdebug_compile_routine/05/test.sql diff --git a/tests/root/rdebug_compile_routine/06/description.txt b/tests/__legacy__/rdebug_compile_routine/06/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/06/description.txt rename to tests/__legacy__/rdebug_compile_routine/06/description.txt diff --git a/tests/root/rdebug_compile_routine/06/test.sql b/tests/__legacy__/rdebug_compile_routine/06/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/06/test.sql rename to tests/__legacy__/rdebug_compile_routine/06/test.sql diff --git a/tests/root/rdebug_compile_routine/07/description.txt b/tests/__legacy__/rdebug_compile_routine/07/description.txt similarity index 100% rename from tests/root/rdebug_compile_routine/07/description.txt rename to tests/__legacy__/rdebug_compile_routine/07/description.txt diff --git a/tests/root/rdebug_compile_routine/07/test.sql b/tests/__legacy__/rdebug_compile_routine/07/test.sql similarity index 100% rename from tests/root/rdebug_compile_routine/07/test.sql rename to tests/__legacy__/rdebug_compile_routine/07/test.sql diff --git a/tests/root/rdebug_compile_routine/pre.sql b/tests/__legacy__/rdebug_compile_routine/pre.sql similarity index 100% rename from tests/root/rdebug_compile_routine/pre.sql rename to tests/__legacy__/rdebug_compile_routine/pre.sql diff --git a/tests/root/sql_range_partitions/01/description.txt b/tests/__legacy__/sql_range_partitions/01/description.txt similarity index 100% rename from tests/root/sql_range_partitions/01/description.txt rename to tests/__legacy__/sql_range_partitions/01/description.txt diff --git a/tests/root/sql_range_partitions/01/expected.txt b/tests/__legacy__/sql_range_partitions/01/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/01/expected.txt rename to tests/__legacy__/sql_range_partitions/01/expected.txt diff --git a/tests/root/sql_range_partitions/01/test.sql b/tests/__legacy__/sql_range_partitions/01/test.sql similarity index 100% rename from tests/root/sql_range_partitions/01/test.sql rename to tests/__legacy__/sql_range_partitions/01/test.sql diff --git a/tests/root/sql_range_partitions/02/description.txt b/tests/__legacy__/sql_range_partitions/02/description.txt similarity index 100% rename from tests/root/sql_range_partitions/02/description.txt rename to tests/__legacy__/sql_range_partitions/02/description.txt diff --git a/tests/root/sql_range_partitions/02/expected.txt b/tests/__legacy__/sql_range_partitions/02/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/02/expected.txt rename to tests/__legacy__/sql_range_partitions/02/expected.txt diff --git a/tests/root/sql_range_partitions/02/test.sql b/tests/__legacy__/sql_range_partitions/02/test.sql similarity index 100% rename from tests/root/sql_range_partitions/02/test.sql rename to tests/__legacy__/sql_range_partitions/02/test.sql diff --git a/tests/root/sql_range_partitions/03/description.txt b/tests/__legacy__/sql_range_partitions/03/description.txt similarity index 100% rename from tests/root/sql_range_partitions/03/description.txt rename to tests/__legacy__/sql_range_partitions/03/description.txt diff --git a/tests/root/sql_range_partitions/03/expected.txt b/tests/__legacy__/sql_range_partitions/03/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/03/expected.txt rename to tests/__legacy__/sql_range_partitions/03/expected.txt diff --git a/tests/root/sql_range_partitions/03/test.sql b/tests/__legacy__/sql_range_partitions/03/test.sql similarity index 100% rename from tests/root/sql_range_partitions/03/test.sql rename to tests/__legacy__/sql_range_partitions/03/test.sql diff --git a/tests/root/sql_range_partitions/04/description.txt b/tests/__legacy__/sql_range_partitions/04/description.txt similarity index 100% rename from tests/root/sql_range_partitions/04/description.txt rename to tests/__legacy__/sql_range_partitions/04/description.txt diff --git a/tests/root/sql_range_partitions/04/expected.txt b/tests/__legacy__/sql_range_partitions/04/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/04/expected.txt rename to tests/__legacy__/sql_range_partitions/04/expected.txt diff --git a/tests/root/sql_range_partitions/04/pre.sql b/tests/__legacy__/sql_range_partitions/04/pre.sql similarity index 100% rename from tests/root/sql_range_partitions/04/pre.sql rename to tests/__legacy__/sql_range_partitions/04/pre.sql diff --git a/tests/root/sql_range_partitions/04/test.sql b/tests/__legacy__/sql_range_partitions/04/test.sql similarity index 100% rename from tests/root/sql_range_partitions/04/test.sql rename to tests/__legacy__/sql_range_partitions/04/test.sql diff --git a/tests/root/sql_range_partitions/05/description.txt b/tests/__legacy__/sql_range_partitions/05/description.txt similarity index 100% rename from tests/root/sql_range_partitions/05/description.txt rename to tests/__legacy__/sql_range_partitions/05/description.txt diff --git a/tests/root/sql_range_partitions/05/expected.txt b/tests/__legacy__/sql_range_partitions/05/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/05/expected.txt rename to tests/__legacy__/sql_range_partitions/05/expected.txt diff --git a/tests/root/sql_range_partitions/05/test.sql b/tests/__legacy__/sql_range_partitions/05/test.sql similarity index 100% rename from tests/root/sql_range_partitions/05/test.sql rename to tests/__legacy__/sql_range_partitions/05/test.sql diff --git a/tests/root/sql_range_partitions/06/description.txt b/tests/__legacy__/sql_range_partitions/06/description.txt similarity index 100% rename from tests/root/sql_range_partitions/06/description.txt rename to tests/__legacy__/sql_range_partitions/06/description.txt diff --git a/tests/root/sql_range_partitions/06/expected.txt b/tests/__legacy__/sql_range_partitions/06/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/06/expected.txt rename to tests/__legacy__/sql_range_partitions/06/expected.txt diff --git a/tests/root/sql_range_partitions/06/pre.sql b/tests/__legacy__/sql_range_partitions/06/pre.sql similarity index 100% rename from tests/root/sql_range_partitions/06/pre.sql rename to tests/__legacy__/sql_range_partitions/06/pre.sql diff --git a/tests/root/sql_range_partitions/06/test.sql b/tests/__legacy__/sql_range_partitions/06/test.sql similarity index 100% rename from tests/root/sql_range_partitions/06/test.sql rename to tests/__legacy__/sql_range_partitions/06/test.sql diff --git a/tests/root/sql_range_partitions/07/description.txt b/tests/__legacy__/sql_range_partitions/07/description.txt similarity index 100% rename from tests/root/sql_range_partitions/07/description.txt rename to tests/__legacy__/sql_range_partitions/07/description.txt diff --git a/tests/root/sql_range_partitions/07/expected.txt b/tests/__legacy__/sql_range_partitions/07/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/07/expected.txt rename to tests/__legacy__/sql_range_partitions/07/expected.txt diff --git a/tests/root/sql_range_partitions/07/test.sql b/tests/__legacy__/sql_range_partitions/07/test.sql similarity index 100% rename from tests/root/sql_range_partitions/07/test.sql rename to tests/__legacy__/sql_range_partitions/07/test.sql diff --git a/tests/root/sql_range_partitions/08/description.txt b/tests/__legacy__/sql_range_partitions/08/description.txt similarity index 100% rename from tests/root/sql_range_partitions/08/description.txt rename to tests/__legacy__/sql_range_partitions/08/description.txt diff --git a/tests/root/sql_range_partitions/08/expected.txt b/tests/__legacy__/sql_range_partitions/08/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/08/expected.txt rename to tests/__legacy__/sql_range_partitions/08/expected.txt diff --git a/tests/root/sql_range_partitions/08/test.sql b/tests/__legacy__/sql_range_partitions/08/test.sql similarity index 100% rename from tests/root/sql_range_partitions/08/test.sql rename to tests/__legacy__/sql_range_partitions/08/test.sql diff --git a/tests/root/sql_range_partitions/09/description.txt b/tests/__legacy__/sql_range_partitions/09/description.txt similarity index 100% rename from tests/root/sql_range_partitions/09/description.txt rename to tests/__legacy__/sql_range_partitions/09/description.txt diff --git a/tests/root/sql_range_partitions/09/expected.txt b/tests/__legacy__/sql_range_partitions/09/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/09/expected.txt rename to tests/__legacy__/sql_range_partitions/09/expected.txt diff --git a/tests/root/sql_range_partitions/09/test.sql b/tests/__legacy__/sql_range_partitions/09/test.sql similarity index 100% rename from tests/root/sql_range_partitions/09/test.sql rename to tests/__legacy__/sql_range_partitions/09/test.sql diff --git a/tests/root/sql_range_partitions/10/description.txt b/tests/__legacy__/sql_range_partitions/10/description.txt similarity index 100% rename from tests/root/sql_range_partitions/10/description.txt rename to tests/__legacy__/sql_range_partitions/10/description.txt diff --git a/tests/root/sql_range_partitions/10/test.sql b/tests/__legacy__/sql_range_partitions/10/test.sql similarity index 100% rename from tests/root/sql_range_partitions/10/test.sql rename to tests/__legacy__/sql_range_partitions/10/test.sql diff --git a/tests/root/sql_range_partitions/11/description.txt b/tests/__legacy__/sql_range_partitions/11/description.txt similarity index 100% rename from tests/root/sql_range_partitions/11/description.txt rename to tests/__legacy__/sql_range_partitions/11/description.txt diff --git a/tests/root/sql_range_partitions/11/test.sql b/tests/__legacy__/sql_range_partitions/11/test.sql similarity index 100% rename from tests/root/sql_range_partitions/11/test.sql rename to tests/__legacy__/sql_range_partitions/11/test.sql diff --git a/tests/root/sql_range_partitions/12/description.txt b/tests/__legacy__/sql_range_partitions/12/description.txt similarity index 100% rename from tests/root/sql_range_partitions/12/description.txt rename to tests/__legacy__/sql_range_partitions/12/description.txt diff --git a/tests/root/sql_range_partitions/12/test.sql b/tests/__legacy__/sql_range_partitions/12/test.sql similarity index 100% rename from tests/root/sql_range_partitions/12/test.sql rename to tests/__legacy__/sql_range_partitions/12/test.sql diff --git a/tests/root/sql_range_partitions/13/description.txt b/tests/__legacy__/sql_range_partitions/13/description.txt similarity index 100% rename from tests/root/sql_range_partitions/13/description.txt rename to tests/__legacy__/sql_range_partitions/13/description.txt diff --git a/tests/root/sql_range_partitions/13/test.sql b/tests/__legacy__/sql_range_partitions/13/test.sql similarity index 100% rename from tests/root/sql_range_partitions/13/test.sql rename to tests/__legacy__/sql_range_partitions/13/test.sql diff --git a/tests/root/sql_range_partitions/14/description.txt b/tests/__legacy__/sql_range_partitions/14/description.txt similarity index 100% rename from tests/root/sql_range_partitions/14/description.txt rename to tests/__legacy__/sql_range_partitions/14/description.txt diff --git a/tests/root/sql_range_partitions/14/expected.txt b/tests/__legacy__/sql_range_partitions/14/expected.txt similarity index 100% rename from tests/root/sql_range_partitions/14/expected.txt rename to tests/__legacy__/sql_range_partitions/14/expected.txt diff --git a/tests/root/sql_range_partitions/14/test.sql b/tests/__legacy__/sql_range_partitions/14/test.sql similarity index 100% rename from tests/root/sql_range_partitions/14/test.sql rename to tests/__legacy__/sql_range_partitions/14/test.sql diff --git a/tests/root/sql_range_partitions/pre.sql b/tests/__legacy__/sql_range_partitions/pre.sql similarity index 100% rename from tests/root/sql_range_partitions/pre.sql rename to tests/__legacy__/sql_range_partitions/pre.sql diff --git a/tests/test_all.sh b/tests/test_all.sh index 7a366c7..c3b98ff 100644 --- a/tests/test_all.sh +++ b/tests/test_all.sh @@ -20,8 +20,9 @@ let num_tests=0 cd $TESTS_ROOT_PATH +echo mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA if [ -f pre.sql ] ; then - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < pre.sql + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < pre.sql if [ $? -ne 0 ] ; then echo "Test startup failed on pre.sql" exit 1 @@ -34,7 +35,7 @@ do echo "Testing family: ${TEST_FAMILY_PATH}" cd $TESTS_ROOT_PATH/$TEST_FAMILY_PATH if [ -f pre.sql ] ; then - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < pre.sql + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < pre.sql if [ $? -ne 0 ] ; then echo "Test family ${TEST_FAMILY_PATH} failed on pre.sql" exit 1 @@ -53,18 +54,18 @@ do export TEST_BRIEF_DESCRIPTION="" fi echo " ${TEST_FAMILY_PATH}/${TEST_PATH}: ${TEST_BRIEF_DESCRIPTION}" - + # prepare test if [ -f pre.sql ] ; then - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < pre.sql + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < pre.sql if [ $? -ne 0 ] ; then echo "Test ${TEST_FAMILY_PATH}/${TEST_PATH} failed on pre.sql" exit 1 fi fi - + # execute test code - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA --silent --raw < test.sql > ${TEST_OUTPUT_PATH}/${TEST_OUTPUT_FILE} 2> ${TEST_OUTPUT_PATH}/${TEST_ERROR_FILE} + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA --silent --raw < test.sql > ${TEST_OUTPUT_PATH}/${TEST_OUTPUT_FILE} 2> ${TEST_OUTPUT_PATH}/${TEST_ERROR_FILE} if [ $? -eq 0 ] ; then # No errors thrown by test itself; check test results if [ -f error_expected.txt ] ; then @@ -80,7 +81,7 @@ do echo "** Output: ${TEST_OUTPUT_PATH}/${TEST_OUTPUT_FILE}" echo "** Expected: $(pwd)/expected.txt" echo "** Diff: ${TEST_OUTPUT_PATH}/${DIFF_OUTPUT_FILE}" - + exit 1 fi elif [ -f expect_no_error.txt ] ; then @@ -110,7 +111,7 @@ do # post test code (typically cleanup) if [ -f post.sql ] ; then - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < post.sql + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < post.sql if [ $? -ne 0 ] ; then echo "Test ${TEST_FAMILY_PATH}/${TEST_PATH} failed on post.sql" exit 1 @@ -120,7 +121,7 @@ do done # Post family code (typicaly cleanup) if [ -f post.sql ] ; then - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < post.sql + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < post.sql if [ $? -ne 0 ] ; then echo "Test family ${TEST_FAMILY_PATH} failed on post.sql" exit 1 @@ -130,7 +131,7 @@ done cd $TESTS_ROOT_PATH if [ -f post.sql ] ; then - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < post.sql + mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --host=localhost --socket=$MYSQL_SOCKET $MYSQL_SCHEMA < post.sql if [ $? -ne 0 ] ; then echo "Test cleanup failed on post.sql" exit 1