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 00000000000..ddb3f2e0748 Binary files /dev/null and b/mysql-test/std_data/vcol_autoinc.MYI differ diff --git a/mysql-test/std_data/vcol_autoinc.frm b/mysql-test/std_data/vcol_autoinc.frm new file mode 100644 index 00000000000..bff7983735c Binary files /dev/null and b/mysql-test/std_data/vcol_autoinc.frm differ 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;