summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc613
1 files changed, 208 insertions, 405 deletions
diff --git a/sql/table.cc b/sql/table.cc
index f33e90d73b8..3d3bc3336ef 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -915,6 +915,54 @@ static uint upgrade_collation(ulong mysql_version, uint cs_number)
}
+void Column_definition_attributes::frm_pack_basic(uchar *buff) const
+{
+ int2store(buff + 3, length);
+ int2store(buff + 8, pack_flag);
+ buff[10]= (uchar) unireg_check;
+}
+
+
+void Column_definition_attributes::frm_unpack_basic(const uchar *buff)
+{
+ length= uint2korr(buff + 3);
+ pack_flag= uint2korr(buff + 8);
+ unireg_check= (Field::utype) MTYP_TYPENR((uint) buff[10]);
+}
+
+
+void Column_definition_attributes::frm_pack_charset(uchar *buff) const
+{
+ buff[11]= (uchar) (charset->number >> 8);
+ buff[14]= (uchar) charset->number;
+}
+
+
+bool Column_definition_attributes::frm_unpack_charset(TABLE_SHARE *share,
+ const uchar *buff)
+{
+ uint cs_org= buff[14] + (((uint) buff[11]) << 8);
+ uint cs_new= upgrade_collation(share->mysql_version, cs_org);
+ if (cs_org != cs_new)
+ share->incompatible_version|= HA_CREATE_USED_CHARSET;
+ if (cs_new && !(charset= get_charset(cs_new, MYF(0))))
+ {
+ const char *csname= get_charset_name((uint) cs_new);
+ char tmp[10];
+ if (!csname || csname[0] =='?')
+ {
+ my_snprintf(tmp, sizeof(tmp), "#%u", cs_new);
+ csname= tmp;
+ }
+ my_printf_error(ER_UNKNOWN_COLLATION,
+ "Unknown collation '%s' in table '%-.64s' definition",
+ MYF(0), csname, share->table_name.str);
+ return true;
+ }
+ return false;
+}
+
+
/*
In MySQL 5.7 the null bits for not stored virtual fields are last.
Calculate the position for these bits
@@ -1145,6 +1193,38 @@ end:
DBUG_RETURN(res);
}
+
+static const Type_handler *old_frm_type_handler(uint pack_flag,
+ uint interval_nr)
+{
+ enum_field_types field_type= (enum_field_types) f_packtype(pack_flag);
+ DBUG_ASSERT(field_type < 16);
+
+ if (!f_is_alpha(pack_flag))
+ return Type_handler::get_handler_by_real_type(field_type);
+
+ if (!f_is_packed(pack_flag))
+ {
+ if (field_type == MYSQL_TYPE_DECIMAL) // 3.23 or 4.0 string
+ return &type_handler_string;
+ if (field_type == MYSQL_TYPE_VARCHAR) // Since mysql-5.0
+ return &type_handler_varchar;
+ return NULL; // Error (bad frm?)
+ }
+
+ if (f_is_blob(pack_flag))
+ return &type_handler_blob; // QQ: exact type??
+
+ if (interval_nr)
+ {
+ if (f_is_enum(pack_flag))
+ return &type_handler_enum;
+ return &type_handler_set;
+ }
+ return Type_handler::get_handler_by_real_type(field_type);
+}
+
+
/**
Read data from a binary .frm file image into a TABLE_SHARE
@@ -1191,8 +1271,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
size_t UNINIT_VAR(options_len);
uchar *vcol_screen_pos;
const uchar *options= 0;
- size_t UNINIT_VAR(gis_options_len);
- const uchar *gis_options= 0;
+ LEX_CUSTRING gis_options= { NULL, 0};
KEY first_keyinfo;
uint len;
uint ext_key_parts= 0;
@@ -1288,10 +1367,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
case EXTRA2_GIS:
#ifdef HAVE_SPATIAL
{
- if (gis_options)
+ if (gis_options.str)
goto err;
- gis_options= extra2;
- gis_options_len= length;
+ gis_options.str= extra2;
+ gis_options.length= length;
}
#endif /*HAVE_SPATIAL*/
break;
@@ -1782,83 +1861,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
- uint pack_flag, interval_nr, unireg_type, recpos, field_length;
- uint vcol_info_length=0;
- uint vcol_expr_length=0;
- enum_field_types field_type;
- CHARSET_INFO *charset=NULL;
- Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
+ uint interval_nr= 0, recpos;
LEX_CSTRING comment;
LEX_CSTRING name;
Virtual_column_info *vcol_info= 0;
- uint gis_length, gis_decimals, srid= 0;
- Field::utype unireg_check;
const Type_handler *handler;
uint32 flags= 0;
+ Column_definition_attributes attr;
if (new_frm_ver >= 3)
{
/* new frm file in 4.1 */
- field_length= uint2korr(strpos+3);
recpos= uint3korr(strpos+5);
- pack_flag= uint2korr(strpos+8);
- unireg_type= (uint) strpos[10];
- interval_nr= (uint) strpos[12];
uint comment_length=uint2korr(strpos+15);
- field_type=(enum_field_types) (uint) strpos[13];
-
- /* charset and geometry_type share the same byte in frm */
- if (field_type == MYSQL_TYPE_GEOMETRY)
- {
-#ifdef HAVE_SPATIAL
- uint gis_opt_read;
- Field_geom::storage_type st_type;
- geom_type= (Field::geometry_type) strpos[14];
- charset= &my_charset_bin;
- gis_opt_read= gis_field_options_read(gis_options, gis_options_len,
- &st_type, &gis_length, &gis_decimals, &srid);
- gis_options+= gis_opt_read;
- gis_options_len-= gis_opt_read;
-#else
- goto err;
-#endif
- }
- else
- {
- uint cs_org= strpos[14] + (((uint) strpos[11]) << 8);
- uint cs_new= upgrade_collation(share->mysql_version, cs_org);
- if (cs_org != cs_new)
- share->incompatible_version|= HA_CREATE_USED_CHARSET;
- if (!cs_new)
- charset= &my_charset_bin;
- else if (!(charset= get_charset(cs_new, MYF(0))))
- {
- const char *csname= get_charset_name((uint) cs_new);
- char tmp[10];
- if (!csname || csname[0] =='?')
- {
- my_snprintf(tmp, sizeof(tmp), "#%u", cs_new);
- csname= tmp;
- }
- my_printf_error(ER_UNKNOWN_COLLATION,
- "Unknown collation '%s' in table '%-.64s' definition",
- MYF(0), csname, share->table_name.str);
- goto err;
- }
- }
-
- if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL)
- {
- if (!interval_nr) // Expect non-null expression
- goto err;
- /*
- MariaDB version 10.0 version.
- The interval_id byte in the .frm file stores the length of the
- expression statement for a virtual column.
- */
- vcol_info_length= interval_nr;
- interval_nr= 0;
- }
if (!comment_length)
{
@@ -1872,32 +1887,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
comment_pos+= comment_length;
}
- if (unireg_type & MYSQL57_GENERATED_FIELD)
+ if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL)
{
- unireg_type&= MYSQL57_GENERATED_FIELD;
-
/*
- MySQL 5.7 generated fields
-
- byte 1 = 1
- byte 2,3 = expr length
- byte 4 = stored_in_db
- byte 5.. = expr
+ MariaDB version 10.0 version.
+ The interval_id byte in the .frm file stores the length of the
+ expression statement for a virtual column.
*/
- if ((uint)(vcol_screen_pos)[0] != 1)
+ uint vcol_info_length= (uint) strpos[12];
+
+ if (!vcol_info_length) // Expect non-null expression
goto err;
- vcol_info= new (&share->mem_root) Virtual_column_info();
- vcol_info_length= uint2korr(vcol_screen_pos + 1);
- DBUG_ASSERT(vcol_info_length);
- vcol_info->stored_in_db= vcol_screen_pos[3];
- vcol_info->utf8= 0;
- vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
- share->virtual_fields++;
- vcol_info_length= 0;
- }
- if (vcol_info_length)
- {
+ attr.frm_unpack_basic(strpos);
+ if (attr.frm_unpack_charset(share, strpos))
+ goto err;
/*
Old virtual field information before 10.2
@@ -1911,7 +1915,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
vcol_info= new (&share->mem_root) Virtual_column_info();
bool opt_interval_id= (uint)vcol_screen_pos[0] == 2;
- field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
+ enum_field_types ftype= (enum_field_types) (uchar) vcol_screen_pos[1];
+ if (!(handler= Type_handler::get_handler_by_real_type(ftype)))
+ goto err;
if (opt_interval_id)
interval_nr= (uint)vcol_screen_pos[3];
else if ((uint)vcol_screen_pos[0] != 1)
@@ -1919,26 +1925,63 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
bool stored= vcol_screen_pos[2] & 1;
vcol_info->stored_in_db= stored;
vcol_info->set_vcol_type(stored ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL);
- vcol_expr_length= vcol_info_length -
- (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id));
+ uint vcol_expr_length= vcol_info_length -
+ (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id));
vcol_info->utf8= 0; // before 10.2.1 the charset was unknown
int2store(vcol_screen_pos+1, vcol_expr_length); // for parse_vcol_defs()
vcol_screen_pos+= vcol_info_length;
share->virtual_fields++;
}
+ else
+ {
+ interval_nr= (uint) strpos[12];
+ enum_field_types field_type= (enum_field_types) strpos[13];
+ if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
+ goto err; // Not supported field type
+ if (handler->Column_definition_attributes_frm_unpack(&attr, share,
+ strpos,
+ &gis_options))
+ goto err;
+ }
+
+ if (((uint) strpos[10]) & MYSQL57_GENERATED_FIELD)
+ {
+ attr.unireg_check= Field::NONE;
+
+ /*
+ MySQL 5.7 generated fields
+
+ byte 1 = 1
+ byte 2,3 = expr length
+ byte 4 = stored_in_db
+ byte 5.. = expr
+ */
+ if ((uint)(vcol_screen_pos)[0] != 1)
+ goto err;
+ vcol_info= new (&share->mem_root) Virtual_column_info();
+ uint vcol_info_length= uint2korr(vcol_screen_pos + 1);
+ DBUG_ASSERT(vcol_info_length);
+ vcol_info->stored_in_db= vcol_screen_pos[3];
+ vcol_info->utf8= 0;
+ vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
+ share->virtual_fields++;
+ }
}
else
{
- field_length= (uint) strpos[3];
+ attr.length= (uint) strpos[3];
recpos= uint2korr(strpos+4),
- pack_flag= uint2korr(strpos+6);
- pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
- unireg_type= (uint) strpos[8];
+ attr.pack_flag= uint2korr(strpos+6);
+ attr.pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
+ attr.unireg_check= (Field::utype) MTYP_TYPENR((uint) strpos[8]);
interval_nr= (uint) strpos[10];
/* old frm file */
- field_type= (enum_field_types) f_packtype(pack_flag);
- if (f_is_binary(pack_flag))
+ enum_field_types ftype= (enum_field_types) f_packtype(attr.pack_flag);
+ if (!(handler= Type_handler::get_handler_by_real_type(ftype)))
+ goto err; // Not supported field type
+
+ if (f_is_binary(attr.pack_flag))
{
/*
Try to choose the best 4.1 type:
@@ -1946,26 +1989,26 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
try to find a binary collation for character set.
- for other types (e.g. BLOB) just use my_charset_bin.
*/
- if (!f_is_blob(pack_flag))
+ if (!f_is_blob(attr.pack_flag))
{
// 3.23 or 4.0 string
- if (!(charset= get_charset_by_csname(share->table_charset->csname,
- MY_CS_BINSORT, MYF(0))))
- charset= &my_charset_bin;
+ if (!(attr.charset= get_charset_by_csname(share->table_charset->csname,
+ MY_CS_BINSORT, MYF(0))))
+ attr.charset= &my_charset_bin;
}
- else
- charset= &my_charset_bin;
}
else
- charset= share->table_charset;
+ attr.charset= share->table_charset;
bzero((char*) &comment, sizeof(comment));
+ if ((!(handler= old_frm_type_handler(attr.pack_flag, interval_nr))))
+ goto err; // Not supported field type
}
/* Remove >32 decimals from old files */
if (share->mysql_version < 100200)
- pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
+ attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
- if (interval_nr && charset->mbminlen > 1)
+ if (interval_nr && attr.charset->mbminlen > 1)
{
/* Unescape UCS2 intervals from HEX notation */
TYPELIB *interval= share->intervals + interval_nr - 1;
@@ -1973,17 +2016,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
#ifndef TO_BE_DELETED_ON_PRODUCTION
- if (field_type == MYSQL_TYPE_NEWDECIMAL && !share->mysql_version)
+ if (handler->real_field_type() == MYSQL_TYPE_NEWDECIMAL &&
+ !share->mysql_version)
{
/*
Fix pack length of old decimal values from 5.0.3 -> 5.0.4
The difference is that in the old version we stored precision
in the .frm table while we now store the display_length
*/
- uint decimals= f_decimals(pack_flag);
- field_length= my_decimal_precision_to_length(field_length,
- decimals,
- f_is_dec(pack_flag) == 0);
+ uint decimals= f_decimals(attr.pack_flag);
+ attr.length=
+ my_decimal_precision_to_length((uint) attr.length, decimals,
+ f_is_dec(attr.pack_flag) == 0);
sql_print_error("Found incompatible DECIMAL field '%s' in %s; "
"Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
share->fieldnames.type_names[i], share->table_name.str,
@@ -2014,7 +2058,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (flags & VERS_SYSTEM_FIELD)
{
- switch (field_type)
+ switch (handler->real_field_type())
{
case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATETIME2:
@@ -2036,22 +2080,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
/* Convert pre-10.2.2 timestamps to use Field::default_value */
- unireg_check= (Field::utype) MTYP_TYPENR(unireg_type);
name.str= fieldnames.type_names[i];
name.length= strlen(name.str);
- if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
- goto err; // Not supported field type
+ attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL;
+ Record_addr addr(record + recpos, null_pos, null_bit_pos);
*field_ptr= reg_field=
- make_field(share, &share->mem_root, record+recpos, (uint32) field_length,
- null_pos, null_bit_pos, pack_flag, handler, charset,
- geom_type, srid, unireg_check,
- (interval_nr ? share->intervals+interval_nr-1 : NULL),
- &name, flags);
+ attr.make_field(share, &share->mem_root, &addr, handler, &name, flags);
if (!reg_field) // Not supported field type
goto err;
- if (unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
- unireg_check == Field::TIMESTAMP_DN_FIELD)
+ if (attr.unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
+ attr.unireg_check == Field::TIMESTAMP_DN_FIELD)
{
reg_field->default_value= new (&share->mem_root) Virtual_column_info();
reg_field->default_value->set_vcol_type(VCOL_DEFAULT);
@@ -2075,10 +2114,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
status_var_increment(thd->status_var.feature_invisible_columns);
if (!reg_field->invisible)
share->visible_fields++;
- if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
+ if (handler->real_field_type() == MYSQL_TYPE_BIT &&
+ !f_bit_as_char(attr.pack_flag))
{
null_bits_are_used= 1;
- if ((null_bit_pos+= field_length & 7) > 7)
+ if ((null_bit_pos+= (uint) (attr.length & 7)) > 7)
{
null_pos++;
null_bit_pos-= 8;
@@ -2101,7 +2141,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
- if (f_no_default(pack_flag))
+ if (f_no_default(attr.pack_flag))
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (reg_field->unireg_check == Field::NEXT_NUMBER)
@@ -2882,7 +2922,7 @@ bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol)
DBUG_RETURN(0);
vcol->expr->walk(&Item::cleanup_excluding_fields_processor, 0, 0);
- DBUG_ASSERT(!vcol->expr->fixed);
+ DBUG_ASSERT(!vcol->expr->is_fixed());
DBUG_RETURN(fix_vcol_expr(thd, vcol));
}
@@ -2937,7 +2977,7 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table,
DBUG_PRINT("info", ("vcol: %p", vcol));
DBUG_ASSERT(func_expr);
- if (func_expr->fixed)
+ if (func_expr->is_fixed())
DBUG_RETURN(0); // nothing to do
if (fix_vcol_expr(thd, vcol))
@@ -2981,7 +3021,7 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table,
of the statement because the field item does not have a field
pointer at that time
*/
- myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_JUST_WARNING : 0;
+ myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_WARNING : 0;
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(warn),
"AUTO_INCREMENT", vcol->get_vcol_type_name(), res.name);
if (!warn)
@@ -3428,17 +3468,6 @@ partititon_err:
(my_bitmap_map*) bitmaps, share->fields, FALSE);
bitmaps+= bitmap_size;
- /* Don't allocate vcol_bitmap if we don't need it */
- if (share->virtual_fields)
- {
- if (!(outparam->def_vcol_set= (MY_BITMAP*)
- alloc_root(&outparam->mem_root, sizeof(*outparam->def_vcol_set))))
- goto err;
- my_bitmap_init(outparam->def_vcol_set,
- (my_bitmap_map*) bitmaps, share->fields, FALSE);
- bitmaps+= bitmap_size;
- }
-
my_bitmap_init(&outparam->has_value_set,
(my_bitmap_map*) bitmaps, share->fields, FALSE);
bitmaps+= bitmap_size;
@@ -3631,7 +3660,7 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
int db_errno)
{
char buff[FN_REFLEN];
- const myf errortype= ME_ERROR+ME_WAITTANG; // Write fatals error to log
+ const myf errortype= ME_ERROR_LOG; // Write fatals error to log
DBUG_ENTER("open_table_error");
DBUG_PRINT("info", ("error: %d db_errno: %d", error, db_errno));
@@ -4887,7 +4916,7 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
if (where)
{
- if (where->fixed)
+ if (where->is_fixed())
where->update_used_tables();
else if (where->fix_fields(thd, &where))
DBUG_RETURN(TRUE);
@@ -5212,7 +5241,7 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure)
main_view->db.str);
const char *name_table= (main_view->view ? main_view->view_name.str :
main_view->table_name.str);
- my_error(ER_VIEW_CHECK_FAILED, MYF(ignore_failure ? ME_JUST_WARNING : 0),
+ my_error(ER_VIEW_CHECK_FAILED, MYF(ignore_failure ? ME_WARNING : 0),
name_db, name_table);
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
@@ -5246,7 +5275,7 @@ int TABLE::verify_constraints(bool ignore_failure)
in_use->is_error())
{
my_error(ER_CONSTRAINT_FAILED,
- MYF(ignore_failure ? ME_JUST_WARNING : 0), (*chk)->name.str,
+ MYF(ignore_failure ? ME_WARNING : 0), (*chk)->name.str,
s->db.str, s->error_table_name());
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
@@ -5902,13 +5931,13 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
('mysql_schema_table' function). So we can return directly the
field. This case happens only for 'show & where' commands.
*/
- DBUG_ASSERT(field && field->fixed);
+ DBUG_ASSERT(field && field->is_fixed());
DBUG_RETURN(field);
}
DBUG_ASSERT(field);
thd->lex->current_select->no_wrap_view_item= TRUE;
- if (!field->fixed)
+ if (!field->is_fixed())
{
if (field->fix_fields(thd, field_ref))
{
@@ -6246,13 +6275,12 @@ void TABLE::clear_column_bitmaps()
Reset column read/write usage. It's identical to:
bitmap_clear_all(&table->def_read_set);
bitmap_clear_all(&table->def_write_set);
- if (s->virtual_fields) bitmap_clear_all(table->def_vcol_set);
The code assumes that the bitmaps are allocated after each other, as
guaranteed by open_table_from_share()
*/
bzero((char*) def_read_set.bitmap,
s->column_bitmap_size * (s->virtual_fields ? 3 : 2));
- column_bitmaps_set(&def_read_set, &def_write_set, def_vcol_set);
+ column_bitmaps_set(&def_read_set, &def_write_set);
rpl_write_set= 0; // Safety
}
@@ -6399,13 +6427,8 @@ void TABLE::mark_columns_needed_for_delete()
Field **reg_field;
for (reg_field= field ; *reg_field ; reg_field++)
{
- Field *cur_field= *reg_field;
- if (cur_field->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))
- {
- bitmap_set_bit(read_set, cur_field->field_index);
- if (cur_field->vcol_info)
- bitmap_set_bit(vcol_set, cur_field->field_index);
- }
+ if ((*reg_field)->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))
+ mark_column_with_deps(*reg_field);
}
need_signal= true;
}
@@ -6484,13 +6507,7 @@ void TABLE::mark_columns_needed_for_update()
if (any_written && !all_read)
{
for (KEY_PART_INFO *kp= k->key_part; kp < kpend; kp++)
- {
- int idx= kp->fieldnr - 1;
- if (bitmap_fast_test_and_set(read_set, idx))
- continue;
- if (field[idx]->vcol_info)
- mark_virtual_col(field[idx]);
- }
+ mark_column_with_deps(field[kp->fieldnr - 1]);
}
}
need_signal= true;
@@ -6687,49 +6704,12 @@ void TABLE::mark_columns_per_binlog_row_image()
DBUG_ASSERT(FALSE);
}
}
- /*
- We have to ensure that all virtual columns that are part of read set
- are calculated.
- */
- if (vcol_set)
- bitmap_union(vcol_set, read_set);
file->column_bitmaps_signal();
}
DBUG_VOID_RETURN;
}
-/*
- @brief Mark a column as virtual used by the query
-
- @param field the field for the column to be marked
-
- @details
- The function marks the column for 'field' as virtual (computed)
- in the bitmap vcol_set.
- If the column is marked for the first time the expression to compute
- the column is traversed and all columns that are occurred there are
- marked in the read_set of the table.
-
- @retval
- TRUE if column is marked for the first time
- @retval
- FALSE otherwise
-*/
-
-bool TABLE::mark_virtual_col(Field *field)
-{
- bool res;
- DBUG_ASSERT(field->vcol_info);
- if (!(res= bitmap_fast_test_and_set(vcol_set, field->field_index)))
- {
- Item *vcol_item= field->vcol_info->expr;
- DBUG_ASSERT(vcol_item);
- vcol_item->walk(&Item::register_field_in_read_map, 1, 0);
- }
- return res;
-}
-
/*
@brief Mark virtual columns for update/insert commands
@@ -6771,13 +6751,13 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
{
tmp_vfield= *vfield_ptr;
if (bitmap_is_set(write_set, tmp_vfield->field_index))
- bitmap_updated|= mark_virtual_col(tmp_vfield);
+ bitmap_updated|= mark_virtual_column_with_deps(tmp_vfield);
else if (tmp_vfield->vcol_info->stored_in_db ||
(tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG |
PART_INDIRECT_KEY_FLAG)))
{
bitmap_set_bit(write_set, tmp_vfield->field_index);
- mark_virtual_col(tmp_vfield);
+ mark_virtual_column_with_deps(tmp_vfield);
bitmap_updated= true;
}
}
@@ -6904,8 +6884,6 @@ void TABLE::mark_columns_used_by_virtual_fields(void)
void TABLE::mark_check_constraint_columns_for_read(void)
{
bitmap_union(read_set, s->check_set);
- if (vcol_set)
- bitmap_union(vcol_set, s->check_set);
}
@@ -7650,6 +7628,20 @@ public:
}
};
+
+/*
+ to satisfy ASSERT_COLUMN_MARKED_FOR_WRITE Field's assert we temporarily
+ mark field for write before storing the generated value in it
+*/
+#ifndef DBUG_OFF
+#define DBUG_FIX_WRITE_SET(f) bool _write_set_fixed= !bitmap_fast_test_and_set(write_set, (f)->field_index)
+#define DBUG_RESTORE_WRITE_SET(f) if (_write_set_fixed) bitmap_clear_bit(write_set, (f)->field_index)
+#else
+#define DBUG_FIX_WRITE_SET(f)
+#define DBUG_RESTORE_WRITE_SET(f)
+#endif
+
+
/*
@brief Compute values for virtual columns used in query
@@ -7713,17 +7705,17 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
switch (update_mode) {
case VCOL_UPDATE_FOR_READ:
update= (!vcol_info->stored_in_db &&
- bitmap_is_set(vcol_set, vf->field_index));
+ bitmap_is_set(read_set, vf->field_index));
swap_values= 1;
break;
case VCOL_UPDATE_FOR_DELETE:
case VCOL_UPDATE_FOR_WRITE:
- update= bitmap_is_set(vcol_set, vf->field_index);
+ update= bitmap_is_set(read_set, vf->field_index);
break;
case VCOL_UPDATE_FOR_REPLACE:
update= ((!vcol_info->stored_in_db &&
(vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
- bitmap_is_set(vcol_set, vf->field_index)) ||
+ bitmap_is_set(read_set, vf->field_index)) ||
update_all_columns);
if (update && (vf->flags & BLOB_FLAG))
{
@@ -7743,7 +7735,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
update= (!vcol_info->stored_in_db &&
(vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
- !bitmap_is_set(vcol_set, vf->field_index));
+ !bitmap_is_set(read_set, vf->field_index));
swap_values= 1;
break;
}
@@ -7752,8 +7744,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
{
int field_error __attribute__((unused)) = 0;
/* Compute the actual value of the virtual fields */
+ DBUG_FIX_WRITE_SET(vf);
if (vcol_info->expr->save_in_field(vf, 0))
field_error= error= 1;
+ DBUG_RESTORE_WRITE_SET(vf);
DBUG_PRINT("info", ("field '%s' - updated error: %d",
vf->field_name.str, field_error));
if (swap_values && (vf->flags & BLOB_FLAG))
@@ -7787,7 +7781,9 @@ int TABLE::update_virtual_field(Field *vf)
in_use->set_n_backup_active_arena(expr_arena, &backup_arena);
bitmap_clear_all(&tmp_set);
vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set);
+ DBUG_FIX_WRITE_SET(vf);
vf->vcol_info->expr->save_in_field(vf, 0);
+ DBUG_RESTORE_WRITE_SET(vf);
in_use->restore_active_arena(expr_arena, &backup_arena);
DBUG_RETURN(in_use->is_error());
}
@@ -8452,200 +8448,6 @@ double KEY::actual_rec_per_key(uint i)
}
-/**
- @brief
- Mark subformulas of a condition unusable for the condition pushed into table
-
- @param cond The condition whose subformulas are to be marked
-
- @details
- This method recursively traverses the AND-OR condition cond and for each subformula
- of the codition it checks whether it can be usable for the extraction of a condition
- that can be pushed into this table. The subformulas that are not usable are
- marked with the flag NO_EXTRACTION_FL.
- @note
- This method is called before any call of TABLE_LIST::build_pushable_cond_for_table.
- The flag NO_EXTRACTION_FL set in a subformula allows to avoid building clone
- for the subformula when extracting the pushable condition.
-*/
-
-void TABLE_LIST::check_pushable_cond_for_table(Item *cond)
-{
- table_map tab_map= table->map;
- cond->clear_extraction_flag();
- if (cond->type() == Item::COND_ITEM)
- {
- bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
- uint count= 0;
- Item *item;
- while ((item=li++))
- {
- check_pushable_cond_for_table(item);
- if (item->get_extraction_flag() != NO_EXTRACTION_FL)
- count++;
- else if (!and_cond)
- break;
- }
- if ((and_cond && count == 0) || item)
- {
- cond->set_extraction_flag(NO_EXTRACTION_FL);
- if (and_cond)
- li.rewind();
- while ((item= li++))
- item->clear_extraction_flag();
- }
- }
- else if (!cond->excl_dep_on_table(tab_map))
- cond->set_extraction_flag(NO_EXTRACTION_FL);
-}
-
-
-/**
- @brief
- Build condition extractable from the given one depended only on this table
-
- @param thd The thread handle
- @param cond The condition from which the pushable one is to be extracted
-
- @details
- For the given condition cond this method finds out what condition depended
- only on this table can be extracted from cond. If such condition C exists
- the method builds the item for it.
- The method uses the flag NO_EXTRACTION_FL set by the preliminary call of
- the method TABLE_LIST::check_pushable_cond_for_table to figure out whether
- a subformula depends only on this table or not.
- @note
- The built condition C is always implied by the condition cond
- (cond => C). The method tries to build the most restictive such
- condition (i.e. for any other condition C' such that cond => C'
- we have C => C').
- @note
- The build item is not ready for usage: substitution for the field items
- has to be done and it has to be re-fixed.
-
- @retval
- the built condition pushable into this table if such a condition exists
- NULL if there is no such a condition
-*/
-
-Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond)
-{
- table_map tab_map= table->map;
- bool is_multiple_equality= cond->type() == Item::FUNC_ITEM &&
- ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC;
- if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
- return 0;
- if (cond->type() == Item::COND_ITEM)
- {
- bool cond_and= false;
- Item_cond *new_cond;
- if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
- {
- cond_and= true;
- new_cond=new (thd->mem_root) Item_cond_and(thd);
- }
- else
- new_cond= new (thd->mem_root) Item_cond_or(thd);
- if (!new_cond)
- return 0;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
- Item *item;
- bool is_fix_needed= false;
- while ((item=li++))
- {
- if (item->get_extraction_flag() == NO_EXTRACTION_FL)
- {
- if (!cond_and)
- return 0;
- continue;
- }
- Item *fix= build_pushable_cond_for_table(thd, item);
- if (!fix && !cond_and)
- return 0;
- if (!fix)
- continue;
-
- if (fix->type() == Item::COND_ITEM &&
- ((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
- is_fix_needed= true;
-
- new_cond->argument_list()->push_back(fix, thd->mem_root);
- }
- if (is_fix_needed && new_cond->fix_fields(thd, 0))
- return 0;
-
- switch (new_cond->argument_list()->elements)
- {
- case 0:
- return 0;
- case 1:
- return new_cond->argument_list()->head();
- default:
- return new_cond;
- }
- }
- else if (is_multiple_equality)
- {
- if (!(cond->used_tables() & tab_map))
- return 0;
- Item *new_cond= NULL;
- int i= 0;
- Item_equal *item_equal= (Item_equal *) cond;
- Item *left_item = item_equal->get_const();
- Item_equal_fields_iterator it(*item_equal);
- Item *item;
- if (!left_item)
- {
- while ((item=it++))
- if (item->used_tables() == tab_map)
- {
- left_item= item;
- break;
- }
- }
- if (!left_item)
- return 0;
- while ((item=it++))
- {
- if (!(item->used_tables() == tab_map))
- continue;
- Item_func_eq *eq= 0;
- Item *left_item_clone= left_item->build_clone(thd);
- Item *right_item_clone= item->build_clone(thd);
- if (left_item_clone && right_item_clone)
- {
- left_item_clone->set_item_equal(NULL);
- right_item_clone->set_item_equal(NULL);
- eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
- left_item_clone);
- }
- if (eq)
- {
- i++;
- switch (i)
- {
- case 1:
- new_cond= eq;
- break;
- case 2:
- new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
- break;
- default:
- ((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
- thd->mem_root);
- }
- }
- }
- if (new_cond)
- new_cond->fix_fields(thd, &new_cond);
- return new_cond;
- }
- else if (cond->get_extraction_flag() != NO_EXTRACTION_FL)
- return cond->build_clone(thd);
- return 0;
-}
-
LEX_CSTRING *fk_option_name(enum_fk_option opt)
{
static LEX_CSTRING names[]=
@@ -9032,7 +8834,8 @@ bool Vers_history_point::resolve_unit(THD *thd)
return false;
if (item->fix_fields_if_needed(thd, &item))
return true;
- return item->this_item()->type_handler_for_system_time()->
+ return item->this_item()->real_type_handler()->
+ type_handler_for_system_time()->
Vers_history_point_resolve_unit(thd, this);
}