summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2009-11-11 20:31:28 -0800
committerIgor Babaev <igor@askmonty.org>2009-11-11 20:31:28 -0800
commite4e1ae0d13da399d53bd91df791b149f3eae796b (patch)
tree850b7b3404210b6bad604ad33b5c9a7437253dbe /sql/sql_base.cc
parent99d8d4402080270289f00465309c7c40c2e5d566 (diff)
parentd749c7e60061fd328e95f74d2d77fc59312da3b1 (diff)
downloadmariadb-git-e4e1ae0d13da399d53bd91df791b149f3eae796b.tar.gz
Merge of the patch introducing virtual columns into maria-5.2
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc161
1 files changed, 147 insertions, 14 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1dad5d3e24b..b6b8377ccc9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1521,21 +1521,23 @@ void close_temporary_tables(THD *thd)
my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id;
/* Set pseudo_thread_id to be that of the processed table */
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
- /*
- Loop forward through all tables within the sublist of
- common pseudo_thread_id to create single DROP query.
+ String db;
+ db.append(table->s->db.str);
+ /* Loop forward through all tables that belong to a common database
+ within the sublist of common pseudo_thread_id to create single
+ DROP query
*/
for (s_query.length(stub_len);
table && is_user_table(table) &&
- tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
+ tmpkeyval(thd, table) == thd->variables.pseudo_thread_id &&
+ table->s->db.length == db.length() &&
+ strcmp(table->s->db.str, db.ptr()) == 0;
table= next)
{
/*
- We are going to add 4 ` around the db/table names and possible more
- due to special characters in the names
+ We are going to add ` around the table names and possible more
+ due to special characters
*/
- append_identifier(thd, &s_query, table->s->db.str, strlen(table->s->db.str));
- s_query.append('.');
append_identifier(thd, &s_query, table->s->table_name.str,
strlen(table->s->table_name.str));
s_query.append(',');
@@ -1548,6 +1550,7 @@ void close_temporary_tables(THD *thd)
Query_log_event qinfo(thd, s_query.ptr(),
s_query.length() - 1 /* to remove trailing ',' */,
0, FALSE, 0);
+ qinfo.db= db.ptr();
thd->variables.character_set_client= cs_save;
mysql_bin_log.write(&qinfo);
thd->variables.pseudo_thread_id= save_pseudo_thread_id;
@@ -5607,6 +5610,9 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
table->covering_keys.intersect(field->part_of_key);
table->merge_keys.merge(field->part_of_key);
+ if (field->vcol_info)
+ table->mark_virtual_col(field);
+
if (thd->mark_used_columns == MARK_COLUMNS_READ)
current_bitmap= table->read_set;
else
@@ -7900,6 +7906,12 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
{
/* Mark fields as used to allow storage engine to optimze access */
bitmap_set_bit(field->table->read_set, field->field_index);
+ /*
+ Mark virtual fields for write and others that the virtual fields
+ depend on for read.
+ */
+ if (field->vcol_info)
+ field->table->mark_virtual_col(field);
if (table)
{
table->covering_keys.intersect(field->part_of_key);
@@ -8111,7 +8123,10 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
Item *value, *fld;
Item_field *field;
TABLE *table= 0;
+ List<TABLE> tbl_list;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
@@ -8145,14 +8160,54 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (rfield->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ rfield->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
+ tbl_list.push_back(table);
+ }
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> it(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= it++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields(table, TRUE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
}
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8188,9 +8243,31 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, fields, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, fields, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers)
+ {
+ TABLE *table= 0;
+ List_iterator_fast<Item> f(fields);
+ Item *fld;
+ Item_field *item_field;
+ if (fields.elements)
+ {
+ fld= (Item_field*)f++;
+ item_field= fld->filed_for_view_update();
+ if (item_field && item_field->field &&
+ (table= item_field->field->table) &&
+ table->vfield)
+ result= update_virtual_fields(table, TRUE);
+ }
+ }
+ return result;
}
@@ -8218,11 +8295,14 @@ bool
fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
+ List<TABLE> tbl_list;
Item *value;
TABLE *table= 0;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
Field *field;
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
only one row.
@@ -8242,12 +8322,52 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (field->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ field->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if (value->save_in_field(field, 0) < 0)
goto err;
+ tbl_list.push_back(table);
}
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields(table, TRUE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8283,9 +8403,22 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, ptr, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, ptr, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers && *ptr)
+ {
+ TABLE *table= (*ptr)->table;
+ if (table->vfield)
+ result= update_virtual_fields(table, TRUE);
+ }
+ return result;
+
}