summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h1
-rw-r--r--sql/field_conv.cc55
-rw-r--r--sql/item.cc42
-rw-r--r--sql/item.h3
4 files changed, 78 insertions, 23 deletions
diff --git a/sql/field.h b/sql/field.h
index b138eb772d8..e822f6a71d6 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -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);
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 606edd84c74..dab96a9b827 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -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)))
{
}
diff --git a/sql/item.cc b/sql/item.cc
index 0ce37cdd593..9b4274ab71d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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,9 +409,42 @@ 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;
diff --git a/sql/item.h b/sql/item.h
index b8903756027..408010d211a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -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);