mirror of
https://github.com/MariaDB/server.git
synced 2025-03-29 18:35:35 +01:00
MDEV-16722: Assertion `type() != NULL_ITEM' failed
We hit this assert during the create of a temporary table field because the current code does not handle the case when the value of the NAME_CONST function is NULL. Fixed this by allowing creation of temporary table fields even for the case when NAME_CONST returns NULL value. Introduced tmp_table_field_from_field_type_maybe_null() function in Item class so both Item_basic_value and Item_name_const can use it. Introduced a virtual method get_func_item() in the Item class.
This commit is contained in:
parent
b05ee14d95
commit
befc09f002
7 changed files with 67 additions and 53 deletions
|
@ -3334,3 +3334,14 @@ d x
|
|||
00:00:01 00:00:02
|
||||
00:00:02 NULL
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-16722: Assertion `type() != NULL_ITEM' failed
|
||||
#
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
SELECT row_number() OVER (order by a) FROM t1 order by NAME_CONST('myname',NULL);
|
||||
row_number() OVER (order by a)
|
||||
1
|
||||
2
|
||||
3
|
||||
drop table t1;
|
||||
|
|
|
@ -2100,3 +2100,12 @@ CREATE TABLE t1 (d time);
|
|||
INSERT INTO t1 VALUES ('00:00:01'),('00:00:02');
|
||||
SELECT *, LEAD(d) OVER (ORDER BY d) AS x FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-16722: Assertion `type() != NULL_ITEM' failed
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
SELECT row_number() OVER (order by a) FROM t1 order by NAME_CONST('myname',NULL);
|
||||
drop table t1;
|
||||
|
|
20
sql/item.cc
20
sql/item.cc
|
@ -1960,7 +1960,6 @@ Item_name_const::Item_name_const(THD *thd, Item *name_arg, Item *val):
|
|||
Item_fixed_hybrid(thd), value_item(val), name_item(name_arg)
|
||||
{
|
||||
Item::maybe_null= TRUE;
|
||||
valid_args= true;
|
||||
if (!name_item->basic_const_item())
|
||||
goto err;
|
||||
|
||||
|
@ -1979,7 +1978,6 @@ Item_name_const::Item_name_const(THD *thd, Item *name_arg, Item *val):
|
|||
}
|
||||
|
||||
err:
|
||||
valid_args= false;
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST");
|
||||
}
|
||||
|
||||
|
@ -1987,24 +1985,16 @@ err:
|
|||
Item::Type Item_name_const::type() const
|
||||
{
|
||||
/*
|
||||
As
|
||||
1. one can try to create the Item_name_const passing non-constant
|
||||
arguments, although it's incorrect and
|
||||
2. the type() method can be called before the fix_fields() to get
|
||||
type information for a further type cast, e.g.
|
||||
if (item->type() == FIELD_ITEM)
|
||||
((Item_field *) item)->...
|
||||
we return NULL_ITEM in the case to avoid wrong casting.
|
||||
|
||||
valid_args guarantees value_item->basic_const_item(); if type is
|
||||
FUNC_ITEM, then we have a fudged item_func_neg() on our hands
|
||||
and return the underlying type.
|
||||
We are guarenteed that value_item->basic_const_item(), if not
|
||||
an error is thrown that WRONG ARGUMENTS are supplied to
|
||||
NAME_CONST function.
|
||||
If type is FUNC_ITEM, then we have a fudged item_func_neg()
|
||||
on our hands and return the underlying type.
|
||||
For Item_func_set_collation()
|
||||
e.g. NAME_CONST('name', 'value' COLLATE collation) we return its
|
||||
'value' argument type.
|
||||
*/
|
||||
if (!valid_args)
|
||||
return NULL_ITEM;
|
||||
Item::Type value_type= value_item->type();
|
||||
if (value_type == FUNC_ITEM)
|
||||
{
|
||||
|
|
24
sql/item.h
24
sql/item.h
|
@ -820,6 +820,10 @@ protected:
|
|||
return tmp_table_field_from_field_type(table);
|
||||
}
|
||||
Field *create_tmp_field_int(TABLE *table, uint convert_int_length);
|
||||
Field *tmp_table_field_from_field_type_maybe_null(TABLE *table,
|
||||
Tmp_field_src *src,
|
||||
const Tmp_field_param *param,
|
||||
bool is_explicit_null);
|
||||
|
||||
void push_note_converted_to_negative_complement(THD *thd);
|
||||
void push_note_converted_to_positive_complement(THD *thd);
|
||||
|
@ -876,6 +880,7 @@ public:
|
|||
expressions with subqueries in the ORDER/GROUP clauses.
|
||||
*/
|
||||
String *val_str() { return val_str(&str_value); }
|
||||
virtual Item_func *get_item_func() { return NULL; }
|
||||
|
||||
const MY_LOCALE *locale_from_val_str();
|
||||
|
||||
|
@ -2574,7 +2579,20 @@ protected:
|
|||
Item_basic_value(THD *thd): Item(thd) {}
|
||||
public:
|
||||
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
|
||||
const Tmp_field_param *param);
|
||||
const Tmp_field_param *param)
|
||||
{
|
||||
|
||||
/*
|
||||
create_tmp_field_ex() for this type of Items is called for:
|
||||
- CREATE TABLE ... SELECT
|
||||
- In ORDER BY: SELECT max(a) FROM t1 GROUP BY a ORDER BY 'const';
|
||||
- In CURSORS:
|
||||
DECLARE c CURSOR FOR SELECT 'test';
|
||||
OPEN c;
|
||||
*/
|
||||
return tmp_table_field_from_field_type_maybe_null(table, src, param,
|
||||
type() == Item::NULL_ITEM);
|
||||
}
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
const Type_all_attributes *get_type_all_attributes_from_const() const
|
||||
{ return this; }
|
||||
|
@ -2915,7 +2933,6 @@ class Item_name_const : public Item_fixed_hybrid
|
|||
{
|
||||
Item *value_item;
|
||||
Item *name_item;
|
||||
bool valid_args;
|
||||
public:
|
||||
Item_name_const(THD *thd, Item *name_arg, Item *val);
|
||||
|
||||
|
@ -2948,7 +2965,8 @@ public:
|
|||
DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1;
|
||||
OPEN c;
|
||||
*/
|
||||
return create_tmp_field_ex_simple(table, src, param);
|
||||
return tmp_table_field_from_field_type_maybe_null(table, src, param,
|
||||
type() == Item::NULL_ITEM);
|
||||
}
|
||||
int save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
|
|
|
@ -3313,11 +3313,8 @@ public:
|
|||
|
||||
inline bool is_cond_and(Item *item)
|
||||
{
|
||||
if (item->type() != Item::COND_ITEM)
|
||||
return FALSE;
|
||||
|
||||
Item_cond *cond_item= (Item_cond*) item;
|
||||
return (cond_item->functype() == Item_func::COND_AND_FUNC);
|
||||
Item_func *func_item= item->get_item_func();
|
||||
return func_item && func_item->functype() == Item_func::COND_AND_FUNC;
|
||||
}
|
||||
|
||||
class Item_cond_or :public Item_cond
|
||||
|
@ -3418,11 +3415,8 @@ public:
|
|||
|
||||
inline bool is_cond_or(Item *item)
|
||||
{
|
||||
if (item->type() != Item::COND_ITEM)
|
||||
return FALSE;
|
||||
|
||||
Item_cond *cond_item= (Item_cond*) item;
|
||||
return (cond_item->functype() == Item_func::COND_OR_FUNC);
|
||||
Item_func *func_item= item->get_item_func();
|
||||
return func_item && func_item->functype() == Item_func::COND_OR_FUNC;
|
||||
}
|
||||
|
||||
Item *and_expressions(Item *a, Item *b, Item **org_item);
|
||||
|
|
|
@ -393,6 +393,7 @@ public:
|
|||
|
||||
bool with_sum_func() const { return m_with_sum_func; }
|
||||
With_sum_func_cache* get_with_sum_func_cache() { return this; }
|
||||
Item_func *get_item_func() { return this; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16616,6 +16616,22 @@ Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
|
|||
*this, table);
|
||||
}
|
||||
|
||||
Field *Item::tmp_table_field_from_field_type_maybe_null(TABLE *table,
|
||||
Tmp_field_src *src,
|
||||
const Tmp_field_param *param,
|
||||
bool is_explicit_null)
|
||||
{
|
||||
DBUG_ASSERT(!param->make_copy_field());
|
||||
DBUG_ASSERT(!is_result_field());
|
||||
Field *result;
|
||||
if ((result= tmp_table_field_from_field_type(table)))
|
||||
{
|
||||
if (result && is_explicit_null)
|
||||
result->is_created_from_null_item= true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Field *Item_sum::create_tmp_field(bool group, TABLE *table)
|
||||
{
|
||||
|
@ -16847,31 +16863,6 @@ Field *Item_func_sp::create_tmp_field_ex(TABLE *table,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
Field *Item_basic_value::create_tmp_field_ex(TABLE *table,
|
||||
Tmp_field_src *src,
|
||||
const Tmp_field_param *param)
|
||||
{
|
||||
/*
|
||||
create_tmp_field_ex() for this type of Items is called for:
|
||||
- CREATE TABLE ... SELECT
|
||||
- In ORDER BY: SELECT max(a) FROM t1 GROUP BY a ORDER BY 'const';
|
||||
- In CURSORS:
|
||||
DECLARE c CURSOR FOR SELECT 'test';
|
||||
OPEN c;
|
||||
*/
|
||||
DBUG_ASSERT(!param->make_copy_field());
|
||||
DBUG_ASSERT(!is_result_field());
|
||||
Field *result;
|
||||
if ((result= tmp_table_field_from_field_type(table)))
|
||||
{
|
||||
if (type() == Item::NULL_ITEM) // Item_null or Item_param
|
||||
result->is_created_from_null_item= true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create field for temporary table.
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue