From f8f90aa75fbe8ab5c543d788f2afe55926ae34cb Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 15 Jan 2013 16:46:27 -0800 Subject: [PATCH] Fixed bug mdev-3938. The original patch with the implementation of virtual columns did not support INSERT DELAYED into tables with virtual columns. This patch fixes the problem. --- mysql-test/suite/vcol/r/vcol_misc.result | 10 ++++++++ mysql-test/suite/vcol/t/vcol_misc.test | 18 +++++++++++++++ sql/mysql_priv.h | 3 +++ sql/sql_base.cc | 3 ++- sql/sql_insert.cc | 29 ++++++++++++++++++++++++ sql/table.cc | 12 ++++++---- 6 files changed, 70 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index a4b2cee4bf6..f679d5eb671 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -182,3 +182,13 @@ a b c 2 3 y 0 1 y,n drop table t1,t2; +CREATE TABLE t1 ( +ts TIMESTAMP, +tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL +) ENGINE=MyISAM; +INSERT INTO t1 (tsv) VALUES (DEFAULT); +INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT); +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +DROP TABLE t1; diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 732003da992..53c04898648 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -178,3 +178,21 @@ insert into t2(a,b) values (7,0), (2,3), (0,1); select * from t2; drop table t1,t2; + +# +# Bug mdev-3938: INSERT DELAYED for a table with virtual columns +# + +CREATE TABLE t1 ( + ts TIMESTAMP, + tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL +) ENGINE=MyISAM; + +INSERT INTO t1 (tsv) VALUES (DEFAULT); + +INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT); + +SELECT COUNT(*) FROM t1; + +DROP TABLE t1; + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b40e40792f9..e9973f4c3de 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2292,6 +2292,9 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg); int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, bool is_create_table); +bool unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, + TABLE *table, Field *field, + LEX_STRING *vcol_expr, bool *error_reported); int readfrm(const char *name, uchar **data, size_t *length); int writefrm(const char* name, const uchar* data, size_t len); int closefrm(TABLE *table, bool free_share); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 04198af84b9..f1257a3668f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8429,7 +8429,8 @@ fill_record(THD * thd, List &fields, List &values, 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) + if ((!rfield->vcol_info || rfield->stored_in_db) && + (value->save_in_field(rfield, 0) < 0) && !ignore_errors) { my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0)); goto err; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9962789029e..f76c2252eb9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2084,6 +2084,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) { my_ptrdiff_t adjust_ptrs; Field **field,**org_field, *found_next_number_field; + Field **vfield; TABLE *copy; TABLE_SHARE *share; uchar *bitmap; @@ -2127,12 +2128,20 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) if (!copy_tmp) goto error; + if (share->vfields) + { + vfield= (Field **) client_thd->alloc((share->vfields+1)*sizeof(Field*)); + if (!vfield) + goto error; + } + /* Copy the TABLE object. */ copy= new (copy_tmp) TABLE; *copy= *table; /* We don't need to change the file handler here */ /* Assign the pointers for the field pointers array and the record. */ field= copy->field= (Field**) (copy + 1); + copy->vfield= vfield; bitmap= (uchar*) (field + share->fields + 1); copy->record[0]= (bitmap + share->column_bitmap_size*3); memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength); @@ -2156,6 +2165,26 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) } *field=0; + if (table->vfield) + { + for (field= copy->field; *field; field++) + { + if ((*field)->vcol_info) + { + bool error_reported= FALSE; + if (unpack_vcol_info_from_frm(client_thd, + client_thd->mem_root, + copy, + *field, + &(*field)->vcol_info->expr_str, + &error_reported)) + goto error; + *vfield++= *field; + } + } + *vfield= 0; + } + /* Adjust timestamp */ if (table->timestamp_field) { diff --git a/sql/table.cc b/sql/table.cc index 5c1e27b87c7..dfc9c2d933c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1925,8 +1925,10 @@ end: @brief Unpack the definition of a virtual column from its linear representation - @parm + @param thd The thread object + @param + mem_root The mem_root object where to allocated memory @param table The table containing the virtual column @param @@ -1956,6 +1958,7 @@ end: TRUE Otherwise */ bool unpack_vcol_info_from_frm(THD *thd, + MEM_ROOT *mem_root, TABLE *table, Field *field, LEX_STRING *vcol_expr, @@ -1981,7 +1984,7 @@ bool unpack_vcol_info_from_frm(THD *thd, "PARSE_VCOL_EXPR ()". */ - if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root, + if (!(vcol_expr_str= (char*) alloc_root(mem_root, vcol_expr->length + parse_vcol_keyword.length + 3))) { @@ -2011,8 +2014,8 @@ bool unpack_vcol_info_from_frm(THD *thd, vcol_arena= table->expr_arena; if (!vcol_arena) { - Query_arena expr_arena(&table->mem_root, Query_arena::INITIALIZED); - if (!(vcol_arena= (Query_arena *) alloc_root(&table->mem_root, + Query_arena expr_arena(mem_root, Query_arena::INITIALIZED); + if (!(vcol_arena= (Query_arena *) alloc_root(mem_root, sizeof(Query_arena)))) goto err; *vcol_arena= expr_arena; @@ -2265,6 +2268,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, if ((*field_ptr)->vcol_info) { if (unpack_vcol_info_from_frm(thd, + &outparam->mem_root, outparam, *field_ptr, &(*field_ptr)->vcol_info->expr_str,