Commit 41540957 authored by Monty's avatar Monty

MDEV-24958 Server crashes in my_strtod ... with DEFAULT(blob)

Fixes also:
MDEV-24942 Server crashes in _ma_rec_pack... with DEFAULT() on BLOB

This was caused by two different bugs, both related to that the default
value for the blob was not calculated before it was used:
- There where now Item_default_value::..result() wrappers, which is
  needed as item in HAVING uses these.  This causes crashes when
  using a reference to a DEFAULT(blob_field) in HAVING. It also
  caused wrong results when used with other fields with default value
  expressions that are not constants.
- create_tmp_field() did not take into account that blob fields with
  default expressions are not yet initialized. Fixed by treating
  Item_default_value(blob) like a normal item expression.
parent 6983ce70
...@@ -846,3 +846,36 @@ t r ...@@ -846,3 +846,36 @@ t r
DROP TABLE t1; DROP TABLE t1;
DROP FUNCTION next_seq_value; DROP FUNCTION next_seq_value;
DROP TABLE series; DROP TABLE series;
#
# MDEV-24958 Server crashes in my_strtod /
# Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob)
#
# MDEV-24942 Server crashes in _ma_rec_pack / _ma_write_blob_record with
# DEFAULT() on BLOB
#
CREATE TABLE t1 (id INT, f MEDIUMTEXT NOT NULL DEFAULT 'A');
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
SELECT f FROM t1 GROUP BY id ORDER BY DEFAULT(f);
f
foo
bar
SELECT DEFAULT(f) AS h FROM t1 HAVING h > 5;
h
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'A'
SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 0;
h
A
A
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'A'
SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 'A';
h
A
A
alter table t1 add column b int default (rand()+1+3);
select default(b) AS h FROM t1 HAVING h > "2";
h
#
#
drop table t1;
...@@ -890,3 +890,23 @@ SELECT t, next_seq_value() r FROM t1 FORCE INDEX(t) ...@@ -890,3 +890,23 @@ SELECT t, next_seq_value() r FROM t1 FORCE INDEX(t)
DROP TABLE t1; DROP TABLE t1;
DROP FUNCTION next_seq_value; DROP FUNCTION next_seq_value;
DROP TABLE series; DROP TABLE series;
--echo #
--echo # MDEV-24958 Server crashes in my_strtod /
--echo # Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob)
--echo #
--echo # MDEV-24942 Server crashes in _ma_rec_pack / _ma_write_blob_record with
--echo # DEFAULT() on BLOB
--echo #
CREATE TABLE t1 (id INT, f MEDIUMTEXT NOT NULL DEFAULT 'A');
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
SELECT f FROM t1 GROUP BY id ORDER BY DEFAULT(f);
SELECT DEFAULT(f) AS h FROM t1 HAVING h > 5;
SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 0;
SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 'A';
alter table t1 add column b int default (rand()+1+3);
--replace_column 1 #
select default(b) AS h FROM t1 HAVING h > "2";
drop table t1;
...@@ -9341,7 +9341,6 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) ...@@ -9341,7 +9341,6 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
} }
thd->column_usage= save_column_usage; thd->column_usage= save_column_usage;
real_arg= arg->real_item(); real_arg= arg->real_item();
if (real_arg->type() != FIELD_ITEM) if (real_arg->type() != FIELD_ITEM)
{ {
...@@ -9364,7 +9363,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) ...@@ -9364,7 +9363,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
def_field->reset_fields(); def_field->reset_fields();
// If non-constant default value expression or a blob // If non-constant default value expression or a blob
if (def_field->default_value && if (def_field->default_value &&
(def_field->default_value->flags || def_field->flags & BLOB_FLAG)) (def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
{ {
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length()); uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
if (!newptr) if (!newptr)
...@@ -9461,6 +9460,48 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) ...@@ -9461,6 +9460,48 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
return Item_field::save_in_field(field_arg, no_conversions); return Item_field::save_in_field(field_arg, no_conversions);
} }
double Item_default_value::val_result()
{
calculate();
return Item_field::val_result();
}
longlong Item_default_value::val_int_result()
{
calculate();
return Item_field::val_int_result();
}
String *Item_default_value::str_result(String* tmp)
{
calculate();
return Item_field::str_result(tmp);
}
bool Item_default_value::val_bool_result()
{
calculate();
return Item_field::val_bool_result();
}
bool Item_default_value::is_null_result()
{
calculate();
return Item_field::is_null_result();
}
my_decimal *Item_default_value::val_decimal_result(my_decimal *decimal_value)
{
calculate();
return Item_field::val_decimal_result(decimal_value);
}
bool Item_default_value::get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate)
{
calculate();
return Item_field::get_date_result(ltime, fuzzydate);
}
table_map Item_default_value::used_tables() const table_map Item_default_value::used_tables() const
{ {
if (!field || !field->default_value) if (!field || !field->default_value)
......
...@@ -5859,6 +5859,16 @@ class Item_default_value : public Item_field ...@@ -5859,6 +5859,16 @@ class Item_default_value : public Item_field
longlong val_int(); longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value); my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate); bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
/* Result variants */
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
my_decimal *val_decimal_result(my_decimal *val);
bool val_bool_result();
bool is_null_result();
bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate);
bool send(Protocol *protocol, st_value *buffer); bool send(Protocol *protocol, st_value *buffer);
int save_in_field(Field *field_arg, bool no_conversions); int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param) bool save_in_param(THD *thd, Item_param *param)
......
...@@ -17224,7 +17224,13 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table) ...@@ -17224,7 +17224,13 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
the record in the original table. the record in the original table.
If modify_item is 0 then fill_record() will update If modify_item is 0 then fill_record() will update
the temporary table the temporary table
@param table_cant_handle_bit_fields
Set to 1 if the temporary table cannot handle bit
fields. Only set for heap tables when the bit field
is part of an index.
@param make_copy_field
Set when using with rollup when we want to have
an exact copy of the field.
@retval @retval
0 on error 0 on error
@retval @retval
...@@ -17261,8 +17267,22 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -17261,8 +17267,22 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return result; return result;
} }
case Item::FIELD_ITEM:
case Item::DEFAULT_VALUE_ITEM: case Item::DEFAULT_VALUE_ITEM:
{
Field *field= ((Item_default_value*) item)->field;
if (field->default_value && (field->flags & BLOB_FLAG))
{
/*
We have to use a copy function when using a blob with default value
as the we have to calcuate the default value before we can use it.
*/
return create_tmp_field_from_item(thd, item, table,
(make_copy_field ? 0 : copy_func),
modify_item);
}
}
/* Fall through */
case Item::FIELD_ITEM:
case Item::CONTEXTUALLY_TYPED_VALUE_ITEM: case Item::CONTEXTUALLY_TYPED_VALUE_ITEM:
case Item::INSERT_VALUE_ITEM: case Item::INSERT_VALUE_ITEM:
case Item::TRIGGER_FIELD_ITEM: case Item::TRIGGER_FIELD_ITEM:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment