Commit b3e3a09e authored by unknown's avatar unknown

Fixed bug in LEFT JOIN ... WHERE not_null_key_column=NULL;


Docs/manual.texi:
  ChangeLog
sql/field.h:
  New virtual function to set a field to null or signal an error
sql/field_conv.cc:
  New function to set a field to null or signal an error
sql/item.cc:
  When setting a field to null internally (for WHERE testing) don't autoconvert NULL -> now() or last_insert_id()
sql/item.h:
  New virtual function to set a field to null or signal an error
parent cba8acc1
......@@ -46942,6 +46942,8 @@ temporary tables used for some (unlikely) @code{GROUP BY} queries.
Fixed a bug in key optimizing handling where the expression
@code{WHERE column_name = key_column_name} was calculated as true
for @code{NULL} values.
@item
Fixed core dump bug when doing @code{LEFT JOIN ... WHERE key_column=NULL}.
@end itemize
@node News-3.23.53, News-3.23.52, News-3.23.54, News-3.23.x
......@@ -1043,6 +1043,7 @@ Field *make_field(char *ptr, uint32 field_length,
uint pack_length_to_packflag(uint type);
uint32 calc_pack_length(enum_field_types type,uint32 length);
bool set_field_to_null(Field *field);
bool set_field_to_null_with_conversions(Field *field);
uint find_enum(TYPELIB *typelib,const char *x, uint length);
ulonglong find_set(TYPELIB *typelib,const char *x, uint length);
bool test_if_int(const char *str,int length);
......
......@@ -112,35 +112,52 @@ static void do_outer_field_to_null_str(Copy_field *copy)
bool
set_field_to_null(Field *field)
{
if (field->maybe_null())
if (field->real_maybe_null())
{
field->set_null();
field->reset();
return 0;
}
else
return 1;
}
bool
set_field_to_null_with_conversions(Field *field)
{
if (field->real_maybe_null())
{
if (field->type() == FIELD_TYPE_TIMESTAMP)
{
((Field_timestamp*) field)->set_time();
return 0; // Ok to set time to NULL
}
field->set_null();
field->reset();
if (field == field->table->next_number_field)
return 0; // field is set in handler.cc
if (current_thd->count_cuted_fields)
{
current_thd->cuted_fields++; // Increment error counter
return 0;
}
if (!current_thd->no_errors)
my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
field->field_name);
return 1;
return 0;
}
/*
Check if this is a special type, which will get a special walue
when set to NULL
*/
if (field->type() == FIELD_TYPE_TIMESTAMP)
{
((Field_timestamp*) field)->set_time();
return 0; // Ok to set time to NULL
}
field->reset();
if (field == field->table->next_number_field)
return 0; // field is set in handler.cc
if (current_thd->count_cuted_fields)
{
current_thd->cuted_fields++; // Increment error counter
return 0;
}
return 0;
if (!current_thd->no_errors)
my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
field->field_name);
return 1;
}
static void do_skip(Copy_field *copy __attribute__((unused)))
{
}
......
......@@ -383,7 +383,7 @@ void Item_field::save_org_in_field(Field *to)
if (field->is_null())
{
null_value=1;
set_field_to_null(to);
set_field_to_null_with_conversions(to);
}
else
{
......@@ -398,7 +398,7 @@ bool Item_field::save_in_field(Field *to)
if (result_field->is_null())
{
null_value=1;
return set_field_to_null(to);
return set_field_to_null_with_conversions(to);
}
else
{
......@@ -409,8 +409,41 @@ bool Item_field::save_in_field(Field *to)
return 0;
}
/*
Store null in field
SYNOPSIS
save_in_field()
field Field where we want to store NULL
DESCRIPTION
This is used on INSERT.
Allow NULL to be inserted in timestamp and auto_increment values
RETURN VALUES
0 ok
1 Field doesn't support NULL values and can't handle 'field = NULL'
*/
bool Item_null::save_in_field(Field *field)
{
return set_field_to_null_with_conversions(field);
}
/*
Store null in field
SYNOPSIS
save_safe_in_field()
field Field where we want to store NULL
RETURN VALUES
0 ok
1 Field doesn't support NULL values
*/
bool Item_null::save_safe_in_field(Field *field)
{
return set_field_to_null(field);
}
......@@ -427,7 +460,7 @@ bool Item::save_in_field(Field *field)
str_value.set_quick(buff,sizeof(buff));
result=val_str(&str_value);
if (null_value)
return set_field_to_null(field);
return set_field_to_null_with_conversions(field);
field->set_notnull();
field->store(result->ptr(),result->length());
str_value.set_quick(0, 0);
......@@ -444,13 +477,14 @@ bool Item::save_in_field(Field *field)
{
longlong nr=val_int();
if (null_value)
return set_field_to_null(field);
return set_field_to_null_with_conversions(field);
field->set_notnull();
field->store(nr);
}
return 0;
}
bool Item_string::save_in_field(Field *field)
{
String *result;
......
......@@ -55,6 +55,8 @@ public:
virtual bool save_in_field(Field *field);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); }
virtual bool save_safe_in_field(Field *field)
{ return save_in_field(field); }
virtual bool send(String *str);
virtual bool eq(const Item *, bool binary_cmp) const;
virtual Item_result result_type () const { return REAL_RESULT; }
......@@ -144,6 +146,7 @@ public:
String *val_str(String *str);
void make_field(Send_field *field);
bool save_in_field(Field *field);
bool save_safe_in_field(Field *field);
enum Item_result result_type () const
{ return STRING_RESULT; }
bool send(String *str);
......
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