summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc134
1 files changed, 118 insertions, 16 deletions
diff --git a/sql/table.cc b/sql/table.cc
index 73b1a6bd9b2..3d3bc3336ef 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1896,7 +1896,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
*/
uint vcol_info_length= (uint) strpos[12];
- DBUG_ASSERT(vcol_info_length); // Expect non-null expression
+ if (!vcol_info_length) // Expect non-null expression
+ goto err;
attr.frm_unpack_basic(strpos);
if (attr.frm_unpack_charset(share, strpos))
@@ -2575,6 +2576,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
reg_field->vcol_info= vcol_info;
share->virtual_fields++;
share->stored_fields--;
+ if (reg_field->flags & BLOB_FLAG)
+ share->virtual_not_stored_blob_fields++;
/* Correct stored_rec_length as non stored fields are last */
recpos= (uint) (reg_field->ptr - record);
if (share->stored_rec_length >= recpos)
@@ -3523,7 +3526,7 @@ partititon_err:
}
}
- outparam->mark_columns_used_by_check_constraints();
+ outparam->mark_columns_used_by_virtual_fields();
if (db_stat)
{
@@ -5260,6 +5263,8 @@ int TABLE::verify_constraints(bool ignore_failure)
if (check_constraints &&
!(in_use->variables.option_bits & OPTION_NO_CHECK_CONSTRAINT_CHECKS))
{
+ if (versioned() && !vers_end_field()->is_max())
+ return VIEW_CHECK_OK;
for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
{
/*
@@ -5271,7 +5276,7 @@ int TABLE::verify_constraints(bool ignore_failure)
{
my_error(ER_CONSTRAINT_FAILED,
MYF(ignore_failure ? ME_WARNING : 0), (*chk)->name.str,
- s->db.str, s->table_name.str);
+ s->db.str, s->error_table_name());
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
}
@@ -5951,6 +5956,8 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
Item *item= (new (thd->mem_root)
Item_direct_view_ref(thd, context, field_ref, view->alias.str,
name, view));
+ if (!item)
+ return NULL;
/*
Force creation of nullable item for the result tmp table for outer joined
views/derived tables.
@@ -6420,7 +6427,7 @@ void TABLE::mark_columns_needed_for_delete()
Field **reg_field;
for (reg_field= field ; *reg_field ; reg_field++)
{
- if ((*reg_field)->flags & PART_KEY_FLAG)
+ if ((*reg_field)->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))
mark_column_with_deps(*reg_field);
}
need_signal= true;
@@ -6746,7 +6753,8 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
if (bitmap_is_set(write_set, tmp_vfield->field_index))
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)))
+ (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_column_with_deps(tmp_vfield);
@@ -6811,27 +6819,64 @@ bool TABLE::check_virtual_columns_marked_for_write()
/*
- Mark fields used by check constraints.
+ Mark fields used by check constraints into s->check_set.
+ Mark all fields used in an expression that is part of an index
+ with PART_INDIRECT_KEY_FLAG
+
This is done once for the TABLE_SHARE the first time the table is opened.
The marking must be done non-destructively to handle the case when
this could be run in parallely by two threads
*/
-void TABLE::mark_columns_used_by_check_constraints(void)
+void TABLE::mark_columns_used_by_virtual_fields(void)
{
MY_BITMAP *save_read_set;
- /* If there is no check constraints or if check_set is already initialized */
- if (!s->check_set || s->check_set_initialized)
+ Field **vfield_ptr;
+
+ /* If there is virtual fields are already initialized */
+ if (s->check_set_initialized)
return;
- save_read_set= read_set;
- read_set= s->check_set;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_lock(&s->LOCK_share);
+ if (s->check_set)
+ {
+ /* Mark fields used by check constraint */
+ save_read_set= read_set;
+ read_set= s->check_set;
+
+ for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
+ (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ read_set= save_read_set;
+ }
- for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
- (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ /*
+ mark all fields that part of a virtual indexed field with
+ PART_INDIRECT_KEY_FLAG. This is used to ensure that all fields
+ that are part of an index exits before write/delete/update.
- read_set= save_read_set;
+ As this code is only executed once per open share, it's reusing
+ existing functionality instead of adding an extra argument to
+ add_field_to_set_processor or adding another processor.
+ */
+ if (vfield)
+ {
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->flags & PART_KEY_FLAG)
+ (*vfield_ptr)->vcol_info->expr->walk(&Item::add_field_to_set_processor,
+ 1, this);
+ }
+ for (uint i= 0 ; i < s->fields ; i++)
+ {
+ if (bitmap_is_set(&tmp_set, i))
+ field[i]->flags|= PART_INDIRECT_KEY_FLAG;
+ }
+ bitmap_clear_all(&tmp_set);
+ }
s->check_set_initialized= 1;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_unlock(&s->LOCK_share);
}
/* Add fields used by CHECK CONSTRAINT to read map */
@@ -6879,6 +6924,52 @@ void TABLE::move_fields(Field **ptr, const uchar *to, const uchar *from)
}
+/*
+ Store all allocated virtual fields blob values
+ Used by InnoDB when calculating virtual fields for it's own internal
+ records
+*/
+
+void TABLE::remember_blob_values(String *blob_storage)
+{
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->type() == MYSQL_TYPE_BLOB &&
+ !(*vfield_ptr)->vcol_info->stored_in_db)
+ {
+ Field_blob *blob= ((Field_blob*) *vfield_ptr);
+ memcpy((void*) blob_storage, (void*) &blob->value, sizeof(blob->value));
+ blob_storage++;
+ blob->value.release();
+ }
+ }
+}
+
+
+/*
+ Restore all allocated virtual fields blob values
+ Used by InnoDB when calculating virtual fields for it's own internal
+ records
+*/
+
+void TABLE::restore_blob_values(String *blob_storage)
+{
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->type() == MYSQL_TYPE_BLOB &&
+ !(*vfield_ptr)->vcol_info->stored_in_db)
+ {
+ Field_blob *blob= ((Field_blob*) *vfield_ptr);
+ blob->value.free();
+ memcpy((void*) &blob->value, (void*) blob_storage, sizeof(blob->value));
+ blob_storage++;
+ }
+ }
+}
+
+
/**
@brief
Allocate space for keys
@@ -7622,7 +7713,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
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) &&
+ update= ((!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
bitmap_is_set(read_set, vf->field_index)) ||
update_all_columns);
if (update && (vf->flags & BLOB_FLAG))
@@ -7641,7 +7733,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
case VCOL_UPDATE_INDEXED:
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
- update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= (!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
!bitmap_is_set(read_set, vf->field_index));
swap_values= 1;
break;
@@ -7777,6 +7870,7 @@ void TABLE::vers_update_fields()
}
vers_end_field()->set_max();
+ bitmap_set_bit(read_set, vers_end_field()->field_index);
}
@@ -8206,7 +8300,15 @@ int TABLE_LIST::fetch_number_of_rows()
{
int error= 0;
if (jtbm_subselect)
+ {
+ if (jtbm_subselect->is_jtbm_merged)
+ {
+ table->file->stats.records= (ha_rows)jtbm_subselect->jtbm_record_count;
+ set_if_bigger(table->file->stats.records, 2);
+ table->used_stat_records= table->file->stats.records;
+ }
return 0;
+ }
if (is_materialized_derived() && !fill_me)
{
table->file->stats.records= ((select_unit*)(get_unit()->result))->records;