From 47687eef41b97edac423b4ff694cdd20cf804901 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 26 Jun 2017 16:26:35 +0200 Subject: [PATCH] MDEV-12936 upgrade to 10.2.6 failed upon tables with virtual columns when opening 10.1- table that has virtual columns: 1. don't error out if it has vcols over autoinc columns. just issue a warning. 2. set vcol type properly 3. in innodb: use table->s->stored_fields instead of table->s->fields, because that's what was stored in innodb data dictionary --- mysql-test/std_data/vcol_autoinc.MYD | 0 mysql-test/std_data/vcol_autoinc.MYI | Bin 0 -> 1024 bytes mysql-test/std_data/vcol_autoinc.frm | Bin 0 -> 951 bytes mysql-test/suite/vcol/r/upgrade.result | 18 +++++++++++++++++ mysql-test/suite/vcol/t/upgrade.test | 13 ++++++++++++ sql/table.cc | 10 ++++++--- storage/innobase/handler/ha_innodb.cc | 27 ++++++++++++++++--------- 7 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 mysql-test/std_data/vcol_autoinc.MYD create mode 100644 mysql-test/std_data/vcol_autoinc.MYI create mode 100644 mysql-test/std_data/vcol_autoinc.frm create mode 100644 mysql-test/suite/vcol/r/upgrade.result create mode 100644 mysql-test/suite/vcol/t/upgrade.test diff --git a/mysql-test/std_data/vcol_autoinc.MYD b/mysql-test/std_data/vcol_autoinc.MYD new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mysql-test/std_data/vcol_autoinc.MYI b/mysql-test/std_data/vcol_autoinc.MYI new file mode 100644 index 0000000000000000000000000000000000000000..ddb3f2e07484ca3409f27799615b02fe213c12d7 GIT binary patch literal 1024 zcmezOkDZZ$fiZ+(149bK5e5*Ofdfba!GAD`h4>Ez5GfWcDsTyLY9Y(O%z@D`xyXPw zFQII(OOW_5CCD_ywG2eNgB7Tm9f(0R2#WwQ6A&}7u`zhDE1|Z7LJkCob_GQFC^;Ge0~!JVGs`1w literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/vcol_autoinc.frm b/mysql-test/std_data/vcol_autoinc.frm new file mode 100644 index 0000000000000000000000000000000000000000..bff7983735ca79b64107cf18c5ab59c86ca758d7 GIT binary patch literal 951 zcmeyz$jK?h5XQjBu$`HK;U^;}0~|0ZGH@_3u!8tN8UlVYGBC)tGcpLk1Q-M^DxXk~ zN)UX$`Ot!nEpysbGME?`7=g;TfJ#_^<^p*QKp|-$=YK$ur>|pB8^ zWALr?40iN|c+j8GACweEFaYKO1~DM!MC2xh0H6pcSiqT#n*p3n_!$_OA^DA)fen~% Y8i3MYfdc;vvj3ME|7T!iW+=!80BSrQ6aWAK literal 0 HcmV?d00001 diff --git a/mysql-test/suite/vcol/r/upgrade.result b/mysql-test/suite/vcol/r/upgrade.result new file mode 100644 index 00000000000..75684bf0e41 --- /dev/null +++ b/mysql-test/suite/vcol/r/upgrade.result @@ -0,0 +1,18 @@ +check table vcol_autoinc for upgrade; +Table Op Msg_type Msg_text +test.vcol_autoinc check Warning Function or expression 'AUTO_INCREMENT' cannot be used in the GENERATED ALWAYS AS clause of `pk` +test.vcol_autoinc check status OK +show create table vcol_autoinc; +Table Create Table +vcol_autoinc CREATE TABLE `vcol_autoinc` ( + `pk` int(11) NOT NULL AUTO_INCREMENT, + `v3` int(11) GENERATED ALWAYS AS (`pk`) VIRTUAL, + PRIMARY KEY (`pk`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from vcol_autoinc; +pk v3 +insert vcol_autoinc (pk) values (1); +select * from vcol_autoinc; +pk v3 +1 1 +drop table vcol_autoinc; diff --git a/mysql-test/suite/vcol/t/upgrade.test b/mysql-test/suite/vcol/t/upgrade.test new file mode 100644 index 00000000000..3e221747dfa --- /dev/null +++ b/mysql-test/suite/vcol/t/upgrade.test @@ -0,0 +1,13 @@ +# +# MDEV-12936 upgrade to 10.2.6 failed upon tables with virtual columns +# +let $datadir=`select @@datadir`; +copy_file std_data/vcol_autoinc.frm $datadir/test/vcol_autoinc.frm; +copy_file std_data/vcol_autoinc.MYD $datadir/test/vcol_autoinc.MYD; +copy_file std_data/vcol_autoinc.MYI $datadir/test/vcol_autoinc.MYI; +check table vcol_autoinc for upgrade; +show create table vcol_autoinc; +select * from vcol_autoinc; +insert vcol_autoinc (pk) values (1); +select * from vcol_autoinc; +drop table vcol_autoinc; diff --git a/sql/table.cc b/sql/table.cc index 10a94dd8212..45a2966407a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1860,7 +1860,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, interval_nr= (uint)vcol_screen_pos[3]; else if ((uint)vcol_screen_pos[0] != 1) goto err; - vcol_info->stored_in_db= vcol_screen_pos[2] & 1; + 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)); vcol_info->utf8= 0; // before 10.2.1 the charset was unknown @@ -2862,9 +2864,11 @@ 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 */ - my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), + myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_JUST_WARNING : 0; + my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(warn), "AUTO_INCREMENT", vcol->get_vcol_type_name(), res.name); - DBUG_RETURN(1); + if (!warn) + DBUG_RETURN(1); } vcol->flags= res.errors; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ac94658687a..68b69e94681 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -291,6 +291,11 @@ void set_my_errno(int err) errno = err; } +static uint mysql_fields(const TABLE *table) +{ + return table->s->frm_version < FRM_VER_EXPRESSSIONS + ? table->s->stored_fields : table->s->fields; +} /** Checks whether the file name belongs to a partition of a table. @param[in] file_name file name @@ -6495,16 +6500,17 @@ ha_innobase::open(const char* name, int, uint) ib_table = open_dict_table(name, norm_name, is_part, ignore_err); + uint n_fields = mysql_fields(table); + if (ib_table != NULL && ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) - && table->s->fields != dict_table_get_n_tot_u_cols(ib_table)) + && n_fields != dict_table_get_n_tot_u_cols(ib_table)) || (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) - && (table->s->fields - != dict_table_get_n_tot_u_cols(ib_table) - 1)))) { + && (n_fields != dict_table_get_n_tot_u_cols(ib_table) - 1)))) { ib::warn() << "Table " << norm_name << " contains " - << dict_table_get_n_user_cols(ib_table) << " user" - " defined columns in InnoDB, but " << table->s->fields + << dict_table_get_n_tot_u_cols(ib_table) << " user" + " defined columns in InnoDB, but " << n_fields << " columns in MariaDB. Please check" " INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and " REFMAN "innodb-troubleshooting.html for how to resolve the" @@ -8033,7 +8039,7 @@ ha_innobase::build_template( /* Below we check column by column if we need to access the clustered index. */ - n_fields = (ulint) table->s->fields; /* number of columns */ + n_fields = (ulint) mysql_fields(table); if (!m_prebuilt->mysql_template) { m_prebuilt->mysql_template = (mysql_row_templ_t*) @@ -8894,6 +8900,7 @@ calc_row_difference( trx_t* const trx = prebuilt->trx; doc_id_t doc_id = FTS_NULL_DOC_ID; ulint num_v = 0; + uint n_fields = mysql_fields(table); ut_ad(!srv_read_only_mode); @@ -8903,7 +8910,7 @@ calc_row_difference( /* We use upd_buff to convert changed fields */ buf = (byte*) upd_buff; - for (i = 0; i < table->s->fields; i++) { + for (i = 0; i < n_fields; i++) { field = table->field[i]; bool is_virtual = innobase_is_v_fld(field); dict_col_t* col; @@ -9285,7 +9292,7 @@ wsrep_calc_row_hash( void *ctx = alloca(my_md5_context_size()); my_md5_init(ctx); - n_fields = table->s->fields; + n_fields = mysql_fields(table); for (i = 0; i < n_fields; i++) { byte null_byte=0; @@ -11352,7 +11359,9 @@ create_table_check_doc_id_col( ULINT_UNDEFINED if column is of the wrong type/name/size */ { - for (ulint i = 0; i < form->s->fields; i++) { + uint n_fields = mysql_fields(form); + + for (ulint i = 0; i < n_fields; i++) { const Field* field; ulint col_type; ulint col_len;