diff options
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 830 |
1 files changed, 408 insertions, 422 deletions
diff --git a/sql/field.cc b/sql/field.cc index 64c51677c0f..60df918bd63 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -80,7 +80,7 @@ const char field_separator=','; NOTE: to avoid 256*256 table, gap in table types numeration is skiped following #defines describe that gap and how to canculate number of fields - and index of field in thia array. + and index of field in this array. */ #define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_BIT + 1) #define FIELDTYPE_TEAR_TO (MYSQL_TYPE_NEWDECIMAL - 1) @@ -231,7 +231,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]= //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP MYSQL_TYPE_FLOAT, MYSQL_TYPE_VARCHAR, //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 - MYSQL_TYPE_FLOAT, MYSQL_TYPE_FLOAT, + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT, //MYSQL_TYPE_DATE MYSQL_TYPE_TIME MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR @@ -1224,7 +1224,8 @@ bool Field::test_if_equality_guarantees_uniqueness(const Item *item) const for temporal columns, so the query: WHERE temporal_column='string' cannot return multiple distinct temporal values. - QQ: perhaps we could allow INT/DECIMAL/DOUBLE types for temporal items. + + TODO: perhaps we could allow INT/DECIMAL/DOUBLE types for temporal items. */ return result_type() == item->result_type(); } @@ -1322,6 +1323,31 @@ bool Field::can_optimize_range(const Item_bool_func *cond, } +int Field::store_hex_hybrid(const char *str, uint length) +{ + DBUG_ASSERT(result_type() != STRING_RESULT); + ulonglong nr; + + if (length > 8) + { + nr= flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX; + goto warn; + } + nr= (ulonglong) longlong_from_hex_hybrid(str, length); + if ((length == 8) && !(flags & UNSIGNED_FLAG) && (nr > LONGLONG_MAX)) + { + nr= LONGLONG_MAX; + goto warn; + } + return store((longlong) nr, true); // Assume hex numbers are unsigned + +warn: + if (!store((longlong) nr, true)) + set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + return 1; +} + + /** Numeric fields base class constructor. */ @@ -1664,9 +1690,8 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, part_of_key_not_clustered(0), part_of_sortkey(0), unireg_check(unireg_check_arg), field_length(length_arg), null_bit(null_bit_arg), is_created_from_null_item(FALSE), - read_stats(NULL), collected_stats(0), - vcol_info(0), - stored_in_db(TRUE) + read_stats(NULL), collected_stats(0), vcol_info(0), check_constraint(0), + default_value(0) { flags=null_ptr ? 0: NOT_NULL_FLAG; comment.str= (char*) ""; @@ -1783,6 +1808,33 @@ int Field::store(const char *to, uint length, CHARSET_INFO *cs, } +static int timestamp_to_TIME(THD *thd, MYSQL_TIME *ltime, my_time_t ts, + ulong sec_part, ulonglong fuzzydate) +{ + thd->time_zone_used= 1; + if (ts == 0 && sec_part == 0) + { + if (fuzzydate & TIME_NO_ZERO_DATE) + return 1; + set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); + } + else + { + thd->variables.time_zone->gmt_sec_to_TIME(ltime, ts); + ltime->second_part= sec_part; + } + return 0; +} + + +int Field::store_timestamp(my_time_t ts, ulong sec_part) +{ + MYSQL_TIME ltime; + THD *thd= get_thd(); + timestamp_to_TIME(thd, <ime, ts, sec_part, 0); + return store_time_dec(<ime, decimals()); +} + /** Pack the field into a format suitable for storage and transfer. @@ -2283,6 +2335,26 @@ Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff) return tmp; } +int Field::set_default() +{ + if (default_value) + { + Query_arena backup_arena; + table->in_use->set_n_backup_active_arena(table->expr_arena, &backup_arena); + int rc= default_value->expr->save_in_field(this, 0); + table->in_use->restore_active_arena(table->expr_arena, &backup_arena); + return rc; + } + /* Copy constant value stored in s->default_values */ + my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values - + table->record[0]); + memcpy(ptr, ptr + l_offset, pack_length()); + if (maybe_null_in_table()) + *null_ptr= ((*null_ptr & (uchar) ~null_bit) | + (null_ptr[l_offset] & null_bit)); + return 0; +} + /**************************************************************************** Field_null, a field that always return NULL @@ -4248,16 +4320,13 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) int Field_longlong::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; - bool error; - longlong res; - - res= double_to_longlong(nr, unsigned_flag, &error); + Converter_double_to_longlong conv(nr, unsigned_flag); - if (error) + if (conv.error()) set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); - int8store(ptr,res); - return error; + int8store(ptr, conv.result()); + return conv.error(); } @@ -4452,13 +4521,13 @@ String *Field_float::val_str(String *val_buffer, char *to=(char*) val_buffer->ptr(); size_t len; - if (dec >= NOT_FIXED_DEC) + if (dec >= FLOATING_POINT_DECIMALS) len= my_gcvt(nr, MY_GCVT_ARG_FLOAT, to_length - 1, to, NULL); else { /* We are safe here because the buffer length is 70, and - fabs(float) < 10^39, dec < NOT_FIXED_DEC. So the resulting string + fabs(float) < 10^39, dec < FLOATING_POINT_DECIMALS. So the resulting string will be not longer than 69 chars + terminating '\0'. */ len= my_fcvt(nr, dec, to, NULL); @@ -4542,7 +4611,7 @@ int Field_float::do_save_field_metadata(uchar *metadata_ptr) void Field_float::sql_type(String &res) const { - if (dec == NOT_FIXED_DEC) + if (dec >= FLOATING_POINT_DECIMALS) { res.set_ascii(STRING_WITH_LEN("float")); } @@ -4623,7 +4692,7 @@ int truncate_double(double *nr, uint field_length, uint dec, return 1; } - if (dec < NOT_FIXED_DEC) + if (dec < FLOATING_POINT_DECIMALS) { uint order= field_length - dec; uint step= array_elements(log_10) - 1; @@ -4658,53 +4727,61 @@ int truncate_double(double *nr, uint field_length, uint dec, /* Convert double to longlong / ulonglong. - If double is outside of range, adjust return value and set error. + If double is outside of the supported range, + adjust m_result and set m_error. - SYNOPSIS - double_to_longlong() - nr Number to convert - unsigned_flag 1 if result is unsigned - error Will be set to 1 in case of overflow. + @param nr Number to convert + @param unsigned_flag true if result is unsigned */ -longlong double_to_longlong(double nr, bool unsigned_flag, bool *error) +Value_source:: +Converter_double_to_longlong::Converter_double_to_longlong(double nr, + bool unsigned_flag) + :m_error(false) { - longlong res; - - *error= 0; - nr= rint(nr); if (unsigned_flag) { if (nr < 0) { - res= 0; - *error= 1; + m_result= 0; + m_error= true; } else if (nr >= (double) ULONGLONG_MAX) { - res= ~(longlong) 0; - *error= 1; + m_result= ~(longlong) 0; + m_error= true; } else - res= (longlong) double2ulonglong(nr); + m_result= (longlong) double2ulonglong(nr); } else { if (nr <= (double) LONGLONG_MIN) { - res= LONGLONG_MIN; - *error= (nr < (double) LONGLONG_MIN); + m_result= LONGLONG_MIN; + m_error= (nr < (double) LONGLONG_MIN); } else if (nr >= (double) (ulonglong) LONGLONG_MAX) { - res= LONGLONG_MAX; - *error= (nr > (double) LONGLONG_MAX); + m_result= LONGLONG_MAX; + m_error= (nr > (double) LONGLONG_MAX); } else - res= (longlong) nr; + m_result= (longlong) nr; } - return res; +} + + +void Value_source:: +Converter_double_to_longlong::push_warning(THD *thd, + double nr, + bool unsigned_flag) +{ + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_DATA_OVERFLOW, ER_THD(thd, ER_DATA_OVERFLOW), + ErrConvDouble(nr).ptr(), + unsigned_flag ? "UNSIGNED INT" : "INT"); } @@ -4729,32 +4806,13 @@ double Field_double::val_real(void) return j; } + longlong Field_double::val_int_from_real(bool want_unsigned_result) { - ASSERT_COLUMN_MARKED_FOR_READ; - double j; - longlong res; - bool error; - float8get(j,ptr); - - res= double_to_longlong(j, want_unsigned_result, &error); - /* - Note, val_uint() is currently used for auto_increment purposes only, - and we want to suppress all warnings in such cases. - If we ever start using val_uint() for other purposes, - val_int_from_real() will need a new separate parameter to - suppress warnings. - */ - if (error && !want_unsigned_result) - { - THD *thd= get_thd(); - ErrConvDouble err(j); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE, - ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "INTEGER", - err.ptr()); - } - return res; + Converter_double_to_longlong conv(val_real(), want_unsigned_result); + if (!want_unsigned_result && conv.error()) + conv.push_warning(get_thd(), Field_double::val_real(), false); + return conv.result(); } @@ -4812,7 +4870,7 @@ String *Field_double::val_str(String *val_buffer, char *to=(char*) val_buffer->ptr(); size_t len; - if (dec >= NOT_FIXED_DEC) + if (dec >= FLOATING_POINT_DECIMALS) len= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, to_length - 1, to, NULL); else len= my_fcvt(nr, dec, to, NULL); @@ -4871,7 +4929,7 @@ int Field_double::do_save_field_metadata(uchar *metadata_ptr) void Field_double::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); - if (dec == NOT_FIXED_DEC) + if (dec >= FLOATING_POINT_DECIMALS) { res.set_ascii(STRING_WITH_LEN("double")); } @@ -4903,12 +4961,12 @@ void Field_double::sql_type(String &res) const field has NOW() as default and is updated when row changes, else it is field which has 0 as default value and is not automatically updated. TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update - automatically (TIMESTAMP DEFAULT NOW()) + automatically (TIMESTAMP DEFAULT NOW()), not used in Field since 10.2.2 TIMESTAMP_UN_FIELD - field which is set on update automatically but has not NOW() as default (but it may has 0 or some other const timestamp as default) (TIMESTAMP ON UPDATE NOW()). TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on - update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW()) + update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW()), not used in Field since 10.2.2 NONE - field which is not auto-set on update with some other than NOW() default value (TIMESTAMP DEFAULT 0). @@ -4945,6 +5003,13 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg, } +int Field_timestamp::save_in_field(Field *to) +{ + ulong sec_part; + my_time_t ts= get_timestamp(&sec_part); + return to->store_timestamp(ts, sec_part); +} + my_time_t Field_timestamp::get_timestamp(const uchar *pos, ulong *sec_part) const { @@ -5071,12 +5136,11 @@ int Field_timestamp::store(longlong nr, bool unsigned_val) } -int Field_timestamp::store_timestamp(Field_timestamp *from) +int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part) { - ulong sec_part; - my_time_t ts= from->get_timestamp(&sec_part); store_TIME(ts, sec_part); - if (!ts && !sec_part && get_thd()->variables.sql_mode & MODE_NO_ZERO_DATE) + if (ts == 0 && sec_part == 0 && + get_thd()->variables.sql_mode & TIME_NO_ZERO_DATE) { ErrConvString s( STRING_WITH_LEN("0000-00-00 00:00:00.000000") - (decimals() ? 6 - decimals() : 7), @@ -5191,22 +5255,9 @@ Field_timestamp::validate_value_in_record(THD *thd, const uchar *record) const bool Field_timestamp::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) { - THD *thd= get_thd(); - thd->time_zone_used= 1; ulong sec_part; - my_time_t temp= get_timestamp(&sec_part); - if (temp == 0 && sec_part == 0) - { /* Zero time is "000000" */ - if (fuzzydate & TIME_NO_ZERO_DATE) - return 1; - set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); - } - else - { - thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp); - ltime->second_part= sec_part; - } - return 0; + my_time_t ts= get_timestamp(&sec_part); + return timestamp_to_TIME(get_thd(), ltime, ts, sec_part, fuzzydate); } @@ -5256,34 +5307,6 @@ int Field_timestamp::set_time() return 0; } -/** - Mark the field as having an explicit default value. - - @param value if available, the value that the field is being set to - - @note - Fields that have an explicit default value should not be updated - automatically via the DEFAULT or ON UPDATE functions. The functions - that deal with data change functionality (INSERT/UPDATE/LOAD), - determine if there is an explicit value for each field before performing - the data change, and call this method to mark the field. - - For timestamp columns, the only case where a column is not marked - as been given a value are: - - It's explicitly assigned with DEFAULT - - We assign NULL to a timestamp field that is defined as NOT NULL. - This is how MySQL has worked since it's start. -*/ - -void Field_timestamp::set_explicit_default(Item *value) -{ - if (((value->type() == Item::DEFAULT_VALUE_ITEM && - !((Item_default_value*)value)->arg) || - (!maybe_null() && value->null_value))) - return; - set_has_explicit_value(); -} - #ifdef NOT_USED static void store_native(ulonglong num, uchar *to, uint bytes) { @@ -5582,7 +5605,7 @@ int Field_temporal_with_date::store(double nr) ErrConvDouble str(nr); longlong tmp= double_to_datetime(nr, <ime, - sql_mode_for_dates(thd), &error); + (uint) sql_mode_for_dates(thd), &error); return store_TIME_with_warning(<ime, &str, error, tmp != -1); } @@ -7185,8 +7208,7 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) */ return field_charset->coll->strnncollsp(field_charset, a_ptr, a_len, - b_ptr, b_len, - 0); + b_ptr, b_len); } @@ -7560,7 +7582,7 @@ int Field_varstring::cmp_max(const uchar *a_ptr, const uchar *b_ptr, a_length, b_ptr+ length_bytes, - b_length,0); + b_length); return diff; } @@ -7583,7 +7605,7 @@ int Field_varstring::key_cmp(const uchar *key_ptr, uint max_key_length) length, key_ptr+ HA_KEY_BLOB_LENGTH, - uint2korr(key_ptr), 0); + uint2korr(key_ptr)); } @@ -7601,8 +7623,7 @@ int Field_varstring::key_cmp(const uchar *a,const uchar *b) a + HA_KEY_BLOB_LENGTH, uint2korr(a), b + HA_KEY_BLOB_LENGTH, - uint2korr(b), - 0); + uint2korr(b)); } @@ -7892,7 +7913,7 @@ void Field_blob::store_length(uchar *i_ptr, uint i_packlength, uint32 i_number) } -uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg) +uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg) const { return (uint32)read_lowendian(pos, packlength_arg); } @@ -7907,16 +7928,12 @@ int Field_blob::copy_value(Field_blob *from) DBUG_ASSERT(field_charset == from->charset()); int rc= 0; uint32 length= from->get_length(); - uchar *data; - from->get_ptr(&data); + uchar *data= from->get_ptr(); if (packlength < from->packlength) { - int well_formed_errors; set_if_smaller(length, Field_blob::max_data_length()); - length= field_charset->cset->well_formed_len(field_charset, - (const char *) data, - (const char *) data + length, - length, &well_formed_errors); + length= (uint32) Well_formed_prefix(field_charset, + (const char *) data, length).length(); rc= report_if_important_data((const char *) data + length, (const char *) data + from->get_length(), true); @@ -7949,12 +7966,11 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) DBUG_ASSERT(length <= max_data_length()); new_length= length; - copy_length= table->in_use->variables.group_concat_max_len; + copy_length= (uint)MY_MIN(UINT_MAX,table->in_use->variables.group_concat_max_len); if (new_length > copy_length) { - int well_formed_error; - new_length= cs->cset->well_formed_len(cs, from, from + copy_length, - new_length, &well_formed_error); + new_length= Well_formed_prefix(cs, + from, copy_length, new_length).length(); table->blob_storage->set_truncated_value(true); } if (!(tmp= table->blob_storage->store(from, new_length))) @@ -8102,8 +8118,7 @@ int Field_blob::cmp(const uchar *a,uint32 a_length, const uchar *b, uint32 b_length) { return field_charset->coll->strnncollsp(field_charset, - a, a_length, b, b_length, - 0); + a, a_length, b, b_length); } @@ -8160,7 +8175,7 @@ uint Field_blob::get_key_image(uchar *buff,uint length, imagetype type_arg) bzero(buff, image_length); return image_length; } - get_ptr(&blob); + blob= get_ptr(); gobj= Geometry::construct(&buffer, (char*) blob, blob_length); if (!gobj || gobj->get_mbr(&mbr, &dummy)) bzero(buff, image_length); @@ -8175,7 +8190,7 @@ uint Field_blob::get_key_image(uchar *buff,uint length, imagetype type_arg) } #endif /*HAVE_SPATIAL*/ - get_ptr(&blob); + blob= get_ptr(); uint local_char_length= length / field_charset->mbmaxlen; local_char_length= my_charpos(field_charset, blob, blob + blob_length, local_char_length); @@ -8269,7 +8284,7 @@ void Field_blob::sort_string(uchar *to,uint length) uchar *blob; uint blob_length=get_length(); - if (!blob_length) + if (!blob_length && field_charset->pad_char == 0) bzero(to,length); else { @@ -8334,7 +8349,7 @@ uchar *Field_blob::pack(uchar *to, const uchar *from, uint max_length) */ if (length > 0) { - get_ptr((uchar**) &from); + from= get_ptr(); memcpy(to+packlength, from,length); } ptr=save; // Restore org row pointer @@ -8363,8 +8378,8 @@ const uchar *Field_blob::unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data) { DBUG_ENTER("Field_blob::unpack"); - DBUG_PRINT("enter", ("to: 0x%lx; from: 0x%lx; param_data: %u", - (ulong) to, (ulong) from, param_data)); + DBUG_PRINT("enter", ("to: %p; from: %p; param_data: %u", + to, from, param_data)); uint const master_packlength= param_data > 0 ? param_data & 0xFF : packlength; if (from + master_packlength > from_end) @@ -8498,7 +8513,7 @@ uint gis_field_options_read(const uchar *buf, uint buf_len, } end_of_record: - return cbuf - buf; + return (uint)(cbuf - buf); } @@ -8580,14 +8595,12 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) geom_type != Field::GEOM_GEOMETRYCOLLECTION && (uint32) geom_type != wkb_type) { - my_printf_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, - ER_THD(get_thd(), ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - MYF(0), - Geometry::ci_collection[geom_type]->m_name.str, - Geometry::ci_collection[wkb_type]->m_name.str, - field_name, - (ulong) table->in_use->get_stmt_da()-> - current_row_for_warning()); + my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0), + Geometry::ci_collection[geom_type]->m_name.str, + Geometry::ci_collection[wkb_type]->m_name.str, + field_name, + (ulong) table->in_use->get_stmt_da()-> + current_row_for_warning()); goto err_exit; } @@ -8977,7 +8990,7 @@ void Field_set::sql_type(String &res) const 0 if the fields are unequally defined */ -bool Field::eq_def(Field *field) +bool Field::eq_def(const Field *field) const { if (real_type() != field->real_type() || charset() != field->charset() || pack_length() != field->pack_length()) @@ -9009,7 +9022,7 @@ static bool compare_type_names(CHARSET_INFO *charset, TYPELIB *t1, TYPELIB *t2) returns 1 if the fields are equally defined */ -bool Field_enum::eq_def(Field *field) +bool Field_enum::eq_def(const Field *field) const { TYPELIB *values; @@ -9086,7 +9099,7 @@ const uchar *Field_enum::unpack(uchar *to, const uchar *from, @return returns 1 if the fields are equally defined */ -bool Field_num::eq_def(Field *field) +bool Field_num::eq_def(const Field *field) const { if (!Field::eq_def(field)) return 0; @@ -9220,8 +9233,8 @@ Field_bit::do_last_null_byte() const bits. On systems with CHAR_BIT > 8 (not very common), the storage will lose the extra bits. */ - DBUG_PRINT("test", ("bit_ofs: %d, bit_len: %d bit_ptr: 0x%lx", - bit_ofs, bit_len, (long) bit_ptr)); + DBUG_PRINT("test", ("bit_ofs: %d, bit_len: %d bit_ptr: %p", + bit_ofs, bit_len, bit_ptr)); uchar *result; if (bit_len == 0) result= null_ptr; @@ -9669,7 +9682,7 @@ Field_bit::unpack(uchar *to, const uchar *from, const uchar *from_end, } -void Field_bit::set_default() +int Field_bit::set_default() { if (bit_len > 0) { @@ -9677,7 +9690,7 @@ void Field_bit::set_default() uchar bits= get_rec_bits(bit_ptr + col_offset, bit_ofs, bit_len); set_rec_bits(bits, bit_ptr, bit_ofs, bit_len); } - Field::set_default(); + return Field::set_default(); } /* @@ -9742,7 +9755,7 @@ void Field_bit_as_char::sql_type(String &res) const Convert create_field::length from number of characters to number of bytes. */ -void Create_field::create_length_to_internal_length(void) +void Column_definition::create_length_to_internal_length(void) { switch (sql_type) { case MYSQL_TYPE_TINY_BLOB: @@ -9754,8 +9767,9 @@ void Create_field::create_length_to_internal_length(void) case MYSQL_TYPE_STRING: case MYSQL_TYPE_VARCHAR: length*= charset->mbmaxlen; - key_length= length; - pack_length= calc_pack_length(sql_type, length); + DBUG_ASSERT(length <= UINT_MAX32); + key_length= (uint32)length; + pack_length= calc_pack_length(sql_type, key_length); break; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: @@ -9770,253 +9784,142 @@ void Create_field::create_length_to_internal_length(void) } else { - pack_length= length / 8; + pack_length= (uint)(length / 8); /* We need one extra byte to store the bits we save among the null bits */ key_length= pack_length + MY_TEST(length & 7); } break; case MYSQL_TYPE_NEWDECIMAL: key_length= pack_length= - my_decimal_get_binary_size(my_decimal_length_to_precision(length, + my_decimal_get_binary_size(my_decimal_length_to_precision((uint)length, decimals, flags & UNSIGNED_FLAG), decimals); break; default: - key_length= pack_length= calc_pack_length(sql_type, length); + key_length= pack_length= calc_pack_length(sql_type, (uint)length); break; } } -/** - Init for a tmp table field. To be extended if need be. -*/ -void Create_field::init_for_tmp_table(enum_field_types sql_type_arg, - uint32 length_arg, uint32 decimals_arg, - bool maybe_null, bool is_unsigned, - uint pack_length_arg) -{ - DBUG_ENTER("Create_field::init_for_tmp_table"); +bool check_expression(Virtual_column_info *vcol, const char *name, + enum_vcol_info_type type) - field_name= ""; - sql_type= sql_type_arg; - char_length= length= length_arg;; - unireg_check= Field::NONE; - interval= 0; - charset= &my_charset_bin; - geom_type= Field::GEOM_GEOMETRY; +{ + bool ret; + Item::vcol_func_processor_result res; - DBUG_PRINT("enter", ("sql_type: %d, length: %u, pack_length: %u", - sql_type_arg, length_arg, pack_length_arg)); + if (!vcol->name.length) + vcol->name.str= const_cast<char*>(name); /* - These pack flags are crafted to get it correctly through the - branches of make_field(). - */ - switch (sql_type_arg) - { - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_SET: - pack_flag= 0; - break; - - case MYSQL_TYPE_GEOMETRY: - pack_flag= FIELDFLAG_GEOM; - break; - - case MYSQL_TYPE_ENUM: - pack_flag= FIELDFLAG_INTERVAL; - break; - - case MYSQL_TYPE_NEWDECIMAL: - DBUG_ASSERT(decimals_arg <= DECIMAL_MAX_SCALE); - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - pack_flag= FIELDFLAG_NUMBER | - (decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT; - break; - - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - pack_flag= FIELDFLAG_BLOB; - break; - - case MYSQL_TYPE_BIT: - pack_flag= FIELDFLAG_NUMBER | FIELDFLAG_TREAT_BIT_AS_CHAR; - break; + Walk through the Item tree checking if all items are valid + to be part of the virtual column + */ + res.errors= 0; + ret= vcol->expr->walk(&Item::check_vcol_func_processor, 0, &res); + vcol->flags= res.errors; - default: - pack_flag= FIELDFLAG_NUMBER; - break; - } + uint filter= VCOL_IMPOSSIBLE; + if (type != VCOL_GENERATED_VIRTUAL && type != VCOL_DEFAULT) + filter|= VCOL_NOT_STRICTLY_DETERMINISTIC; - /* - Set the pack flag correctly for the blob-like types. This sets the - packtype to something that make_field can use. If the pack type is - not set correctly, the packlength will be reeeeally wierd (like - 129 or so). - */ - switch (sql_type_arg) + if (ret || (res.errors & filter)) { - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_GEOMETRY: - // If you are going to use the above types, you have to pass a - // pack_length as parameter. Assert that is really done. - DBUG_ASSERT(pack_length_arg != ~0U); - pack_flag|= pack_length_to_packflag(pack_length_arg); - break; - default: - /* Nothing */ - break; + my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), res.name, + vcol_type_name(type), name); + return TRUE; } - - pack_flag|= - (maybe_null ? FIELDFLAG_MAYBE_NULL : 0) | - (is_unsigned ? 0 : FIELDFLAG_DECIMAL); - - DBUG_PRINT("debug", ("pack_flag: %s%s%s%s%s%s, pack_type: %d", - FLAGSTR(pack_flag, FIELDFLAG_BINARY), - FLAGSTR(pack_flag, FIELDFLAG_NUMBER), - FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), - FLAGSTR(pack_flag, FIELDFLAG_GEOM), - FLAGSTR(pack_flag, FIELDFLAG_BLOB), - FLAGSTR(pack_flag, FIELDFLAG_DECIMAL), - f_packtype(pack_flag))); - vcol_info= 0; - create_if_not_exists= FALSE; - stored_in_db= TRUE; - - DBUG_VOID_RETURN; -} - - -static inline bool is_item_func(Item* x) -{ - return x != NULL && x->type() == Item::FUNC_ITEM; + /* + Safe to call before fix_fields as long as vcol's don't include sub + queries (which is now checked in check_vcol_func_processor) + */ + if (vcol->expr->check_cols(1)) + return TRUE; + return FALSE; } -bool Create_field::check(THD *thd) +bool Column_definition::check(THD *thd) { const uint conditional_type_modifiers= AUTO_INCREMENT_FLAG; uint sign_len, allowed_type_modifier= 0; ulong max_field_charlength= MAX_FIELD_CHARLENGTH; - DBUG_ENTER("Create_field::check"); + DBUG_ENTER("Column_definition::check"); + /* Initialize data for a computed field */ if (vcol_info) { + DBUG_ASSERT(vcol_info->expr); vcol_info->set_field_type(sql_type); - sql_type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL; - } - - if (length > MAX_FIELD_BLOBLENGTH) - { - my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH); - DBUG_RETURN(1); + if (check_expression(vcol_info, field_name, vcol_info->stored_in_db + ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL)) + DBUG_RETURN(TRUE); } - if (decimals >= NOT_FIXED_DEC) - { - my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals), - field_name, static_cast<ulong>(NOT_FIXED_DEC - 1)); - DBUG_RETURN(TRUE); - } + if (check_constraint && + check_expression(check_constraint, field_name, VCOL_CHECK_FIELD)) + DBUG_RETURN(1); - if (def) + if (default_value) { - /* - Default value should be literal => basic constants => - no need fix_fields() + Item *def_expr= default_value->expr; + if (check_expression(default_value, field_name, VCOL_DEFAULT)) + DBUG_RETURN(TRUE); - We allow only one function as part of default value - - NOW() as default for TIMESTAMP and DATETIME type. - */ - if (def->type() == Item::FUNC_ITEM && - (static_cast<Item_func*>(def)->functype() != Item_func::NOW_FUNC || - (mysql_type_to_time_type(sql_type) != MYSQL_TIMESTAMP_DATETIME) || - def->decimals < length)) + /* Constant's are stored in the 'empty_record', except for blobs */ + if (def_expr->basic_const_item()) { - my_error(ER_INVALID_DEFAULT, MYF(0), field_name); - DBUG_RETURN(1); - } - else if (def->type() == Item::NULL_ITEM) - { - def= 0; - if ((flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG) + if (def_expr->type() == Item::NULL_ITEM) { - my_error(ER_INVALID_DEFAULT, MYF(0), field_name); - DBUG_RETURN(1); + default_value= 0; + if ((flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG) + { + my_error(ER_INVALID_DEFAULT, MYF(0), field_name); + DBUG_RETURN(1); + } } } - else if (flags & AUTO_INCREMENT_FLAG) - { - my_error(ER_INVALID_DEFAULT, MYF(0), field_name); - DBUG_RETURN(1); - } } - if (is_item_func(def)) + if (default_value && (flags & AUTO_INCREMENT_FLAG)) { - /* There is a function default for insertions. */ - def= NULL; - unireg_check= (is_item_func(on_update) ? - Field::TIMESTAMP_DNUN_FIELD : // for insertions and for updates. - Field::TIMESTAMP_DN_FIELD); // only for insertions. - } - else - { - /* No function default for insertions. Either NULL or a constant. */ - if (is_item_func(on_update)) - unireg_check= Field::TIMESTAMP_UN_FIELD; // function default for updates - else - unireg_check= ((flags & AUTO_INCREMENT_FLAG) ? - Field::NEXT_NUMBER : // Automatic increment. - Field::NONE); - } - - if (on_update && - (mysql_type_to_time_type(sql_type) != MYSQL_TIMESTAMP_DATETIME || - on_update->decimals < length)) - { - my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name); + my_error(ER_INVALID_DEFAULT, MYF(0), field_name); DBUG_RETURN(1); } - /* Initialize data for a computed field */ - if (sql_type == MYSQL_TYPE_VIRTUAL) + if (default_value && !default_value->expr->basic_const_item() && + mysql_type_to_time_type(sql_type) == MYSQL_TIMESTAMP_DATETIME && + default_value->expr->type() == Item::FUNC_ITEM) { - DBUG_ASSERT(vcol_info && vcol_info->expr_item); - stored_in_db= vcol_info->is_stored(); /* - Walk through the Item tree checking if all items are valid - to be part of the virtual column + Special case: NOW() for TIMESTAMP and DATETIME fields are handled + as in MariaDB 10.1 by marking them in unireg_check. */ - if (vcol_info->expr_item->walk(&Item::check_vcol_func_processor, 0, NULL)) + Item_func *fn= static_cast<Item_func*>(default_value->expr); + if (fn->functype() == Item_func::NOW_FUNC && + (fn->decimals == 0 || fn->decimals >= length)) { - my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name); - DBUG_RETURN(TRUE); + default_value= 0; + unireg_check= Field::TIMESTAMP_DN_FIELD; } + } - /* - Make a field created for the real type. - Note that regular and computed fields differ from each other only by - Field::vcol_info. It is is always NULL for a column that is not - computed. - */ - sql_type= vcol_info->get_real_type(); + if (on_update) + { + if (mysql_type_to_time_type(sql_type) != MYSQL_TIMESTAMP_DATETIME || + on_update->decimals < length) + { + my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name); + DBUG_RETURN(TRUE); + } + unireg_check= unireg_check == Field::NONE ? Field::TIMESTAMP_UN_FIELD + : Field::TIMESTAMP_DNUN_FIELD; } + else if (flags & AUTO_INCREMENT_FLAG) + unireg_check= Field::NEXT_NUMBER; sign_len= flags & UNSIGNED_FLAG ? 0 : 1; @@ -10049,6 +9952,12 @@ bool Create_field::check(THD *thd) case MYSQL_TYPE_NULL: break; case MYSQL_TYPE_NEWDECIMAL: + if (decimals >= NOT_FIXED_DEC) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals), + field_name, static_cast<uint>(NOT_FIXED_DEC - 1)); + DBUG_RETURN(TRUE); + } my_decimal_trim(&length, &decimals); if (length > DECIMAL_MAX_PRECISION) { @@ -10062,9 +9971,9 @@ bool Create_field::check(THD *thd) DBUG_RETURN(TRUE); } length= - my_decimal_precision_to_length(length, decimals, flags & UNSIGNED_FLAG); + my_decimal_precision_to_length((uint)length, decimals, flags & UNSIGNED_FLAG); pack_length= - my_decimal_get_binary_size(length, decimals); + my_decimal_get_binary_size((uint)length, decimals); break; case MYSQL_TYPE_VARCHAR: /* @@ -10080,33 +9989,6 @@ bool Create_field::check(THD *thd) case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_GEOMETRY: - if (def) - { - /* Allow empty as default value. */ - String str,*res; - res= def->val_str(&str); - /* - A default other than '' is always an error, and any non-NULL - specified default is an error in strict mode. - */ - if (res->length() || thd->is_strict_mode()) - { - my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), - field_name); /* purecov: inspected */ - DBUG_RETURN(TRUE); - } - else - { - /* - Otherwise a default of '' is just a warning. - */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_BLOB_CANT_HAVE_DEFAULT, - ER_THD(thd, ER_BLOB_CANT_HAVE_DEFAULT), - field_name); - } - def= 0; - } flags|= BLOB_FLAG; break; case MYSQL_TYPE_YEAR: @@ -10128,6 +10010,12 @@ bool Create_field::check(THD *thd) my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name); DBUG_RETURN(TRUE); } + if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals), + field_name, static_cast<uint>(FLOATING_POINT_DECIMALS-1)); + DBUG_RETURN(TRUE); + } break; case MYSQL_TYPE_DOUBLE: allowed_type_modifier= AUTO_INCREMENT_FLAG; @@ -10142,6 +10030,12 @@ bool Create_field::check(THD *thd) my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name); DBUG_RETURN(TRUE); } + if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals), + field_name, static_cast<uint>(FLOATING_POINT_DECIMALS-1)); + DBUG_RETURN(TRUE); + } break; case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_TIMESTAMP2: @@ -10201,14 +10095,14 @@ bool Create_field::check(THD *thd) static_cast<ulong>(MAX_BIT_FIELD_LENGTH)); DBUG_RETURN(TRUE); } - pack_length= (length + 7) / 8; + pack_length= ((uint)length + 7) / 8; break; } case MYSQL_TYPE_DECIMAL: DBUG_ASSERT(0); /* Was obsolete */ } /* Remember the value of length */ - char_length= length; + char_length= (uint)length; /* Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and @@ -10216,7 +10110,7 @@ bool Create_field::check(THD *thd) We need to do this check here and in mysql_create_prepare_table() as sp_head::fill_field_definition() calls this function. */ - if (!def && unireg_check == Field::NONE && (flags & NOT_NULL_FLAG)) + if (!default_value && unireg_check == Field::NONE && (flags & NOT_NULL_FLAG)) { /* TIMESTAMP columns get implicit DEFAULT value when @@ -10231,7 +10125,7 @@ bool Create_field::check(THD *thd) if (!(flags & BLOB_FLAG) && ((length > max_field_charlength && - (sql_type != MYSQL_TYPE_VARCHAR || def)) || + sql_type != MYSQL_TYPE_VARCHAR) || (length == 0 && sql_type != MYSQL_TYPE_ENUM && sql_type != MYSQL_TYPE_SET && sql_type != MYSQL_TYPE_STRING && sql_type != MYSQL_TYPE_VARCHAR && @@ -10245,6 +10139,12 @@ bool Create_field::check(THD *thd) field_name, max_field_charlength); /* purecov: inspected */ DBUG_RETURN(TRUE); } + else if (length > MAX_FIELD_BLOBLENGTH) + { + my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH); + DBUG_RETURN(1); + } + if ((~allowed_type_modifier) & flags & conditional_type_modifiers) { my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); @@ -10456,19 +10356,29 @@ Field *make_field(TABLE_SHARE *share, f_is_zerofill(pack_flag) != 0, f_is_dec(pack_flag) == 0); case MYSQL_TYPE_FLOAT: + { + int decimals= f_decimals(pack_flag); + if (decimals == FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; return new (mem_root) Field_float(ptr,field_length,null_pos,null_bit, unireg_check, field_name, - f_decimals(pack_flag), + decimals, f_is_zerofill(pack_flag) != 0, f_is_dec(pack_flag)== 0); + } case MYSQL_TYPE_DOUBLE: + { + int decimals= f_decimals(pack_flag); + if (decimals == FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; return new (mem_root) Field_double(ptr,field_length,null_pos,null_bit, unireg_check, field_name, - f_decimals(pack_flag), + decimals, f_is_zerofill(pack_flag) != 0, f_is_dec(pack_flag)== 0); + } case MYSQL_TYPE_TINY: return new (mem_root) Field_tiny(ptr,field_length,null_pos,null_bit, @@ -10578,10 +10488,10 @@ Field *make_field(TABLE_SHARE *share, /** Create a field suitable for create of table. */ -Create_field::Create_field(THD *thd, Field *old_field, Field *orig_field) +Column_definition::Column_definition(THD *thd, Field *old_field, + Field *orig_field) { - field= old_field; - field_name=change=old_field->field_name; + field_name= old_field->field_name; length= old_field->field_length; flags= old_field->flags; unireg_check=old_field->unireg_check; @@ -10592,10 +10502,9 @@ Create_field::Create_field(THD *thd, Field *old_field, Field *orig_field) comment= old_field->comment; decimals= old_field->decimals(); vcol_info= old_field->vcol_info; - create_if_not_exists= FALSE; - stored_in_db= old_field->stored_in_db; + default_value= orig_field ? orig_field->default_value : 0; + check_constraint= orig_field ? orig_field->check_constraint : 0; option_list= old_field->option_list; - option_struct= old_field->option_struct; switch (sql_type) { case MYSQL_TYPE_BLOB: @@ -10638,6 +10547,15 @@ Create_field::Create_field(THD *thd, Field *old_field, Field *orig_field) buff, "YEAR(4)"); } break; + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + /* + Floating points are stored with FLOATING_POINT_DECIMALS but internally + in MariaDB used with NOT_FIXED_DEC, which is >= FLOATING_POINT_DECIMALS. + */ + if (decimals >= FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; + break; default: break; } @@ -10646,8 +10564,7 @@ Create_field::Create_field(THD *thd, Field *old_field, Field *orig_field) interval= ((Field_enum*) old_field)->typelib; else interval=0; - def=0; - char_length= length; + char_length= (uint)length; /* Copy the default (constant/function) from the column object orig_field, if @@ -10655,40 +10572,31 @@ Create_field::Create_field(THD *thd, Field *old_field, Field *orig_field) - The column allows a default. - - The column type is not a BLOB type. + - The column type is not a BLOB type (as BLOB's doesn't have constant + defaults) - The original column (old_field) was properly initialized with a record buffer pointer. + + - The column didn't have a default expression */ if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && - old_field->ptr != NULL && - orig_field != NULL) + old_field->ptr != NULL && orig_field != NULL) { - bool default_now= false; - if (real_type_with_now_as_default(sql_type)) - { - // The SQL type of the new field allows a function default: - default_now= orig_field->has_insert_default_function(); - bool update_now= orig_field->has_update_default_function(); - - if (default_now && update_now) - unireg_check= Field::TIMESTAMP_DNUN_FIELD; - else if (default_now) - unireg_check= Field::TIMESTAMP_DN_FIELD; - else if (update_now) - unireg_check= Field::TIMESTAMP_UN_FIELD; - } - if (!default_now) // Give a constant default + if (orig_field->unireg_check != Field::NEXT_NUMBER) + unireg_check= orig_field->unireg_check; + + /* Get the value from default_values */ + const uchar *dv= orig_field->table->s->default_values; + if (!default_value && !orig_field->is_null_in_record(dv)) { - /* Get the value from default_values */ - const uchar *dv= orig_field->table->s->default_values; - if (!orig_field->is_null_in_record(dv)) - { - StringBuffer<MAX_FIELD_WIDTH> tmp(charset); - String *res= orig_field->val_str(&tmp, orig_field->ptr_in_record(dv)); - char *pos= (char*) sql_strmake(res->ptr(), res->length()); - def= new (thd->mem_root) Item_string(thd, pos, res->length(), charset); - } + StringBuffer<MAX_FIELD_WIDTH> tmp(charset); + String *res= orig_field->val_str(&tmp, orig_field->ptr_in_record(dv)); + char *pos= (char*) thd->strmake(res->ptr(), res->length()); + default_value= new (thd->mem_root) Virtual_column_info(); + default_value->expr= + new (thd->mem_root) Item_string(thd, pos, res->length(), charset); + default_value->utf8= 0; } } } @@ -10708,7 +10616,7 @@ Create_field::Create_field(THD *thd, Field *old_field, Field *orig_field) length */ -uint32 Field_blob::char_length() +uint32 Field_blob::char_length() const { switch (packlength) { @@ -10739,6 +10647,20 @@ Create_field *Create_field::clone(MEM_ROOT *mem_root) const return res; } +/** + Return true if default is an expression that must be saved explicitely + + This is: + - Not basic constants + - If field is a BLOB (Which doesn't support normal DEFAULT) +*/ + +bool Column_definition::has_default_expression() +{ + return (default_value && + (!default_value->expr->basic_const_item() || + (flags & BLOB_FLAG))); +} /** maximum possible display length for blob. @@ -10895,12 +10817,13 @@ key_map Field::get_possible_keys() analyzed to check if it really should count as a value. */ -void Field::set_explicit_default(Item *value) +bool Field::set_explicit_default(Item *value) { if (value->type() == Item::DEFAULT_VALUE_ITEM && !((Item_default_value*)value)->arg) - return; + return false; set_has_explicit_value(); + return true; } @@ -10921,3 +10844,66 @@ bool Field::validate_value_in_record_with_warn(THD *thd, const uchar *record) dbug_tmp_restore_column_map(table->read_set, old_map); return rc; } + + +bool Field::save_in_field_default_value(bool view_error_processing) +{ + THD *thd= table->in_use; + + if (flags & NO_DEFAULT_VALUE_FLAG && + real_type() != MYSQL_TYPE_ENUM) + { + if (reset()) + { + my_message(ER_CANT_CREATE_GEOMETRY_OBJECT, + ER_THD(thd, ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0)); + return true; + } + + if (view_error_processing) + { + TABLE_LIST *view= table->pos_in_table_list->top_table(); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_VIEW_FIELD, + ER_THD(thd, ER_NO_DEFAULT_FOR_VIEW_FIELD), + view->view_db.str, + view->view_name.str); + } + else + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_FIELD, + ER_THD(thd, ER_NO_DEFAULT_FOR_FIELD), + field_name); + } + return true; + } + set_default(); + return + !is_null() && + validate_value_in_record_with_warn(thd, table->record[0]) && + thd->is_error(); +} + + +bool Field::save_in_field_ignore_value(bool view_error_processing) +{ + enum_sql_command com= table->in_use->lex->sql_command; + // All insert-like commands + if (com == SQLCOM_INSERT || com == SQLCOM_REPLACE || + com == SQLCOM_INSERT_SELECT || com == SQLCOM_REPLACE_SELECT || + com == SQLCOM_LOAD) + return save_in_field_default_value(view_error_processing); + return 0; // ignore +} + + +void Field::register_field_in_read_map() +{ + if (vcol_info) + { + Item *vcol_item= vcol_info->expr; + vcol_item->walk(&Item::register_field_in_read_map, 1, 0); + } + bitmap_set_bit(table->read_set, field_index); +} |