diff --git a/mysql-test/r/sp-row.result b/mysql-test/r/sp-row.result index c3204fe043b..61c0660cf71 100644 --- a/mysql-test/r/sp-row.result +++ b/mysql-test/r/sp-row.result @@ -2246,3 +2246,13 @@ b 10 DROP PROCEDURE p1; DROP TABLE t1; +# +# MDEV-13527 Crash when EXPLAIN SELECT .. INTO row_sp_variable.field +# +BEGIN NOT ATOMIC +DECLARE a ROW(a INT); +EXPLAIN SELECT 1 INTO a.a; +END; +$$ +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used diff --git a/mysql-test/suite/compat/oracle/r/sp-row.result b/mysql-test/suite/compat/oracle/r/sp-row.result index 86b6b9a530b..16421cd45ac 100644 --- a/mysql-test/suite/compat/oracle/r/sp-row.result +++ b/mysql-test/suite/compat/oracle/r/sp-row.result @@ -3070,3 +3070,14 @@ b 10 DROP PROCEDURE p1; DROP TABLE t1; +# +# MDEV-13527 Crash when EXPLAIN SELECT .. INTO row_sp_variable.field +# +DECLARE +a ROW(a INT); +BEGIN +EXPLAIN SELECT 1 INTO a.a; +END; +$$ +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used diff --git a/mysql-test/suite/compat/oracle/t/sp-row.test b/mysql-test/suite/compat/oracle/t/sp-row.test index 5d97bf02fa2..94cc5db9802 100644 --- a/mysql-test/suite/compat/oracle/t/sp-row.test +++ b/mysql-test/suite/compat/oracle/t/sp-row.test @@ -2375,3 +2375,16 @@ DELIMITER ;$$ CALL p1; DROP PROCEDURE p1; DROP TABLE t1; + +--echo # +--echo # MDEV-13527 Crash when EXPLAIN SELECT .. INTO row_sp_variable.field +--echo # + +DELIMITER $$; +DECLARE + a ROW(a INT); +BEGIN + EXPLAIN SELECT 1 INTO a.a; +END; +$$ +DELIMITER ;$$ diff --git a/mysql-test/t/sp-row.test b/mysql-test/t/sp-row.test index 6ed8b4495f4..e213d4dbc2d 100644 --- a/mysql-test/t/sp-row.test +++ b/mysql-test/t/sp-row.test @@ -1471,3 +1471,16 @@ DELIMITER ;$$ CALL p1; DROP PROCEDURE p1; DROP TABLE t1; + + +--echo # +--echo # MDEV-13527 Crash when EXPLAIN SELECT .. INTO row_sp_variable.field +--echo # + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE a ROW(a INT); + EXPLAIN SELECT 1 INTO a.a; +END; +$$ +DELIMITER ;$$ diff --git a/sql/item.cc b/sql/item.cc index 7d3f8788c3f..f84c2aff0a3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -109,36 +109,6 @@ void Item::push_note_converted_to_positive_complement(THD *thd) } -/** - @todo - Make this functions class dependent -*/ - -bool Item::val_bool() -{ - switch(result_type()) { - case INT_RESULT: - return val_int() != 0; - case DECIMAL_RESULT: - { - my_decimal decimal_value; - my_decimal *val= val_decimal(&decimal_value); - if (val) - return !my_decimal_is_zero(val); - return 0; - } - case REAL_RESULT: - case STRING_RESULT: - return val_real() != 0.0; - case ROW_RESULT: - case TIME_RESULT: - DBUG_ASSERT(0); - return 0; // Wrong (but safe) - } - return 0; // Wrong (but safe) -} - - /** Get date/time/datetime. Optionally extend TIME result to DATETIME. diff --git a/sql/item.h b/sql/item.h index 1f487999e83..75c14c6338a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1047,7 +1047,10 @@ public: FALSE value is false or NULL TRUE value is true (not equal to 0) */ - virtual bool val_bool(); + virtual bool val_bool() + { + return type_handler()->Item_val_bool(this); + } virtual String *val_nodeset(String*) { return 0; } /* diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 6e99655c28b..906bc5d0acf 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -3077,6 +3077,38 @@ bool Type_handler_geometry:: #endif +/*************************************************************************/ + +bool Type_handler_real_result::Item_val_bool(Item *item) const +{ + return item->val_real() != 0.0; +} + +bool Type_handler_int_result::Item_val_bool(Item *item) const +{ + return item->val_int() != 0; +} + +bool Type_handler_decimal_result::Item_val_bool(Item *item) const +{ + my_decimal decimal_value; + my_decimal *val= item->val_decimal(&decimal_value); + if (val) + return !my_decimal_is_zero(val); + return false; +} + +bool Type_handler_temporal_result::Item_val_bool(Item *item) const +{ + return item->val_real() != 0.0; +} + +bool Type_handler_string_result::Item_val_bool(Item *item) const +{ + return item->val_real() != 0.0; +} + + /*************************************************************************/ longlong Type_handler_real_result:: diff --git a/sql/sql_type.h b/sql/sql_type.h index 27fb8a8f7da..e6a1d8f31ff 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -891,6 +891,7 @@ public: virtual bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0; + virtual bool Item_val_bool(Item *item) const= 0; virtual longlong Item_val_int_signed_typecast(Item *item) const= 0; virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0; @@ -1147,6 +1148,11 @@ public: DBUG_ASSERT(0); return true; } + bool Item_val_bool(Item *item) const + { + DBUG_ASSERT(0); + return false; + } longlong Item_val_int_signed_typecast(Item *item) const { DBUG_ASSERT(0); @@ -1352,6 +1358,7 @@ public: bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const; + bool Item_val_bool(Item *item) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -1427,6 +1434,7 @@ public: bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; + bool Item_val_bool(Item *item) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -1494,6 +1502,7 @@ public: bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; + bool Item_val_bool(Item *item) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -1564,6 +1573,7 @@ public: bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; + bool Item_val_bool(Item *item) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -1673,6 +1683,7 @@ public: bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const; + bool Item_val_bool(Item *item) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e3a52696fcd..377be90056c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -12156,7 +12156,7 @@ select_outvar: } | ident '.' ident { - if (!($$= Lex->create_outvar(thd, &$1, &$3))) + if (!($$= Lex->create_outvar(thd, &$1, &$3)) && Lex->result) MYSQL_YYABORT; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 8a909617567..c5e8a75d125 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -12219,7 +12219,7 @@ select_outvar: } | ident '.' ident { - if (!($$= Lex->create_outvar(thd, &$1, &$3))) + if (!($$= Lex->create_outvar(thd, &$1, &$3)) && Lex->result) MYSQL_YYABORT; } ;