summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2020-08-11 00:38:32 +1000
committerNikita Malyavin <nikitamalyavin@gmail.com>2020-09-01 18:27:09 +1000
commit97db6c15ea3e83a21df137c222dbd5a40fbe7c82 (patch)
treed642bc3637adbeef1dc084c94b8bc922419877fb
parenta3d66090c789dfd9f31a63187ef2cf7a85df9c1b (diff)
downloadmariadb-git-97db6c15ea3e83a21df137c222dbd5a40fbe7c82.tar.gz
MDEV-20618 Assertion failed in row_upd_sec_index_entry
Add a proper error handling of innobase_get_computed_value results in row_upd_store_row/row_upd_store_v_row. Also add an assertion in row_vers_build_clust_v_col to fail during row purge. Add one more assertion in row_sel_sec_rec_is_for_clust_rec for possible future catches.
-rw-r--r--mysql-test/suite/gcol/inc/gcol_keys.inc62
-rw-r--r--mysql-test/suite/gcol/r/gcol_keys_innodb.result50
-rw-r--r--mysql-test/suite/gcol/r/gcol_keys_myisam.result50
-rw-r--r--mysql-test/suite/vcol/r/vcol_misc.result6
-rw-r--r--mysql-test/suite/vcol/t/vcol_misc.test2
-rw-r--r--sql/sql_insert.cc6
-rw-r--r--storage/innobase/handler/ha_innodb.cc15
-rw-r--r--storage/innobase/include/row0mysql.h6
-rw-r--r--storage/innobase/row/row0sel.cc64
-rw-r--r--storage/innobase/row/row0upd.cc50
-rw-r--r--storage/innobase/row/row0vers.cc28
11 files changed, 280 insertions, 59 deletions
diff --git a/mysql-test/suite/gcol/inc/gcol_keys.inc b/mysql-test/suite/gcol/inc/gcol_keys.inc
index 97c9e41b5e8..475ab96e56f 100644
--- a/mysql-test/suite/gcol/inc/gcol_keys.inc
+++ b/mysql-test/suite/gcol/inc/gcol_keys.inc
@@ -747,4 +747,66 @@ ANALYZE TABLE t1, t2;
--eval $query
DROP TABLE t1, t2;
+if($support_virtual_index)
+{
+--echo #
+--echo # MDEV-20618 Assertion `btr_validate_index(index, 0, false)' failed
+--echo # in row_upd_sec_index_entry
+--echo #
+CREATE TABLE t1 (A BIT(15), VA BIT(10) GENERATED ALWAYS AS (A),PK INT,
+ PRIMARY KEY (PK), UNIQUE KEY (VA));
+
+INSERT IGNORE INTO t1 VALUES ( '\r1','a',1);
+--error ER_DATA_TOO_LONG
+REPLACE INTO t1 (PK) VALUES (1);
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-17890 Record in index was not found on update, server crash in
+--echo # row_upd_build_difference_binary or
+--echo # Assertion `0' failed in row_upd_sec_index_entry
+--echo #
+CREATE TABLE t1 (
+ pk BIGINT AUTO_INCREMENT,
+ b BIT(15),
+ v BIT(10) AS (b) VIRTUAL,
+ PRIMARY KEY(pk),
+ UNIQUE(v)
+);
+
+INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101');
+SELECT pk, b INTO OUTFILE 'load.data' FROM t1;
+--error ER_DATA_TOO_LONG
+LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b);
+
+--let $datadir= `SELECT @@datadir`
+--remove_file $datadir/test/load.data
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-17834 Server crashes in row_upd_build_difference_binary
+--echo # on LOAD DATA into table with indexed virtual column
--echo #
+CREATE TABLE t1 (
+ pk INT,
+ i TINYINT,
+ ts TIMESTAMP NULL,
+ vi TINYINT AS (i+1) PERSISTENT,
+ vts TIMESTAMP(5) AS (ts) VIRTUAL,
+ PRIMARY KEY(pk),
+ UNIQUE(vts)
+);
+
+INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
+
+--write_file $MYSQLTEST_VARDIR/tmp/load.data
+1 4 2019-01-01 00:00:00
+EOF
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--error ER_WARN_DATA_OUT_OF_RANGE
+eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/load.data' REPLACE INTO TABLE t1 (pk,i,ts);
+
+--remove_file $MYSQLTEST_VARDIR/tmp/load.data
+DROP TABLE t1;
+}
diff --git a/mysql-test/suite/gcol/r/gcol_keys_innodb.result b/mysql-test/suite/gcol/r/gcol_keys_innodb.result
index 04ba512aad9..ae2843dd2ec 100644
--- a/mysql-test/suite/gcol/r/gcol_keys_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_keys_innodb.result
@@ -825,6 +825,56 @@ a1 a2 b
0 NULL 1
DROP TABLE t1, t2;
#
+# MDEV-20618 Assertion `btr_validate_index(index, 0, false)' failed
+# in row_upd_sec_index_entry
+#
+CREATE TABLE t1 (A BIT(15), VA BIT(10) GENERATED ALWAYS AS (A),PK INT,
+PRIMARY KEY (PK), UNIQUE KEY (VA));
+INSERT IGNORE INTO t1 VALUES ( '\r1','a',1);
+Warnings:
+Warning 1906 The value specified for generated column 'VA' in table 't1' has been ignored
+Warning 1264 Out of range value for column 'VA' at row 1
+REPLACE INTO t1 (PK) VALUES (1);
+ERROR 22001: Data too long for column 'VA' at row 1
+DROP TABLE t1;
+#
+# MDEV-17890 Record in index was not found on update, server crash in
+# row_upd_build_difference_binary or
+# Assertion `0' failed in row_upd_sec_index_entry
+#
+CREATE TABLE t1 (
+pk BIGINT AUTO_INCREMENT,
+b BIT(15),
+v BIT(10) AS (b) VIRTUAL,
+PRIMARY KEY(pk),
+UNIQUE(v)
+);
+INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101');
+Warnings:
+Warning 1264 Out of range value for column 'v' at row 1
+SELECT pk, b INTO OUTFILE 'load.data' FROM t1;
+LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b);
+ERROR 22001: Data too long for column 'v' at row 1
+DROP TABLE t1;
+#
+# MDEV-17834 Server crashes in row_upd_build_difference_binary
+# on LOAD DATA into table with indexed virtual column
+#
+CREATE TABLE t1 (
+pk INT,
+i TINYINT,
+ts TIMESTAMP NULL,
+vi TINYINT AS (i+1) PERSISTENT,
+vts TIMESTAMP(5) AS (ts) VIRTUAL,
+PRIMARY KEY(pk),
+UNIQUE(vts)
+);
+INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
+Warnings:
+Warning 1264 Out of range value for column 'vi' at row 1
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/load.data' REPLACE INTO TABLE t1 (pk,i,ts);
+ERROR 22003: Out of range value for column 'vi' at row 1
+DROP TABLE t1;
#
# BUG#21365158 WL8149:ASSERTION `!TABLE || (!TABLE->WRITE_SET
#
diff --git a/mysql-test/suite/gcol/r/gcol_keys_myisam.result b/mysql-test/suite/gcol/r/gcol_keys_myisam.result
index dcbba1f70c1..a91a77aedf3 100644
--- a/mysql-test/suite/gcol/r/gcol_keys_myisam.result
+++ b/mysql-test/suite/gcol/r/gcol_keys_myisam.result
@@ -827,6 +827,56 @@ a1 a2 b
0 NULL 1
DROP TABLE t1, t2;
#
+# MDEV-20618 Assertion `btr_validate_index(index, 0, false)' failed
+# in row_upd_sec_index_entry
+#
+CREATE TABLE t1 (A BIT(15), VA BIT(10) GENERATED ALWAYS AS (A),PK INT,
+PRIMARY KEY (PK), UNIQUE KEY (VA));
+INSERT IGNORE INTO t1 VALUES ( '\r1','a',1);
+Warnings:
+Warning 1906 The value specified for generated column 'VA' in table 't1' has been ignored
+Warning 1264 Out of range value for column 'VA' at row 1
+REPLACE INTO t1 (PK) VALUES (1);
+ERROR 22001: Data too long for column 'VA' at row 1
+DROP TABLE t1;
+#
+# MDEV-17890 Record in index was not found on update, server crash in
+# row_upd_build_difference_binary or
+# Assertion `0' failed in row_upd_sec_index_entry
+#
+CREATE TABLE t1 (
+pk BIGINT AUTO_INCREMENT,
+b BIT(15),
+v BIT(10) AS (b) VIRTUAL,
+PRIMARY KEY(pk),
+UNIQUE(v)
+);
+INSERT IGNORE INTO t1 (b) VALUES (b'101110001110100'),(b'011101');
+Warnings:
+Warning 1264 Out of range value for column 'v' at row 1
+SELECT pk, b INTO OUTFILE 'load.data' FROM t1;
+LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b);
+ERROR 22001: Data too long for column 'v' at row 1
+DROP TABLE t1;
+#
+# MDEV-17834 Server crashes in row_upd_build_difference_binary
+# on LOAD DATA into table with indexed virtual column
+#
+CREATE TABLE t1 (
+pk INT,
+i TINYINT,
+ts TIMESTAMP NULL,
+vi TINYINT AS (i+1) PERSISTENT,
+vts TIMESTAMP(5) AS (ts) VIRTUAL,
+PRIMARY KEY(pk),
+UNIQUE(vts)
+);
+INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
+Warnings:
+Warning 1264 Out of range value for column 'vi' at row 1
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/load.data' REPLACE INTO TABLE t1 (pk,i,ts);
+ERROR 22003: Out of range value for column 'vi' at row 1
+DROP TABLE t1;
DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2,t3;
DROP PROCEDURE IF EXISTS p1;
diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result
index a9b5bc29018..6c4975f2178 100644
--- a/mysql-test/suite/vcol/r/vcol_misc.result
+++ b/mysql-test/suite/vcol/r/vcol_misc.result
@@ -456,8 +456,7 @@ select pk, col_bit+0, vcol_bit+0 from t1;
pk col_bit+0 vcol_bit+0
99 10000 1023
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
-Warnings:
-Warning 1264 Out of range value for column 'vcol_bit' at row 1
+ERROR 22001: Data too long for column 'vcol_bit' at row 1
drop table t1;
#
# MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status()
@@ -476,8 +475,7 @@ INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
Warnings:
Warning 1264 Out of range value for column 'vi' at row 1
REPLACE INTO t1 (pk,i) VALUES (1,2);
-Warnings:
-Warning 1264 Out of range value for column 'vi' at row 1
+ERROR 22003: Out of range value for column 'vi' at row 1
DROP TABLE t1;
SET @sql_mode=@old_sql_mode;
#
diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test
index 73b23c78977..07f96f4e0b8 100644
--- a/mysql-test/suite/vcol/t/vcol_misc.test
+++ b/mysql-test/suite/vcol/t/vcol_misc.test
@@ -431,6 +431,7 @@ replace INTO `t1` (`pk`,col_bit) VALUES (99,1000);
select pk, col_bit+0, vcol_bit+0 from t1;
replace INTO `t1` (`pk`,col_bit) VALUES (99,10000);
select pk, col_bit+0, vcol_bit+0 from t1;
+--error ER_DATA_TOO_LONG
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
drop table t1;
@@ -451,6 +452,7 @@ CREATE TABLE t1 (
INSERT INTO t1 (pk,i) VALUES (1,1);
TRUNCATE TABLE t1;
INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
+--error ER_WARN_DATA_OUT_OF_RANGE
REPLACE INTO t1 (pk,i) VALUES (1,2);
DROP TABLE t1;
SET @sql_mode=@old_sql_mode;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ec784bc6df4..0c50a251d26 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1748,15 +1748,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
if (table->vfield)
{
- my_bool abort_on_warning= thd->abort_on_warning;
/*
We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ)
in handler methods for the just read row in record[1].
*/
table->move_fields(table->field, table->record[1], table->record[0]);
- thd->abort_on_warning= 0;
- table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE);
- thd->abort_on_warning= abort_on_warning;
+ if (table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE))
+ goto err;
table->move_fields(table->field, table->record[0], table->record[1]);
}
if (info->handle_duplicates == DUP_UPDATE)
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index d396c71da5f..3b404928cf4 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -103,6 +103,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include "srv0mon.h"
#include "srv0srv.h"
#include "srv0start.h"
+#include "rem0rec.h"
#ifdef UNIV_DEBUG
#include "trx0purge.h"
#endif /* UNIV_DEBUG */
@@ -21881,6 +21882,13 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage)
}
+void innobase_report_computed_value_failed(dtuple_t *row)
+{
+ ib::error() << "Compute virtual column values failed for "
+ << rec_printer(row).str();
+}
+
+
/** Get the computed value by supplying the base column values.
@param[in,out] row the data row
@param[in] col virtual column
@@ -22008,13 +22016,6 @@ innobase_get_computed_value(
dbug_tmp_restore_column_map(mysql_table->write_set, old_write_set);
if (ret != 0) {
- // FIXME: Why this error message is macro-hidden?
-#ifdef INNODB_VIRTUAL_DEBUG
- ib::warn() << "Compute virtual column values failed ";
- fputs("InnoDB: Cannot compute value for following record ",
- stderr);
- dtuple_print(stderr, row);
-#endif /* INNODB_VIRTUAL_DEBUG */
DBUG_RETURN(NULL);
}
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 3b177ac1a24..d5cdd4a3f17 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -874,6 +874,12 @@ public:
}
};
+/** Report virtual value computation failure in ib::error
+@param[in] row the data row
+*/
+ATTRIBUTE_COLD
+void innobase_report_computed_value_failed(dtuple_t *row);
+
/** Get the computed value by supplying the base column values.
@param[in,out] row the data row
@param[in] col virtual column
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index bb15625f748..7fd0210dbab 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -154,11 +154,15 @@ fields are compared with collation!
must be protected by a page s-latch
@param[in] clust_index clustered index
@param[in] thr query thread
-@return TRUE if the secondary record is equal to the corresponding
-fields in the clustered record, when compared with collation;
-FALSE if not equal or if the clustered record has been marked for deletion */
+@retval DB_COMPUTE_VALUE_FAILED in case of virtual column value computation
+ failure.
+@retval DB_SUCCESS_LOCKED_REC if the secondary record is equal to the
+ corresponding fields in the clustered record, when compared with
+ collation;
+@retval DB_SUCCESS if not equal or if the clustered record has been marked
+ for deletion */
static
-ibool
+dberr_t
row_sel_sec_rec_is_for_clust_rec(
const rec_t* sec_rec,
dict_index_t* sec_index,
@@ -190,7 +194,7 @@ row_sel_sec_rec_is_for_clust_rec(
it is not visible in the read view. Besides,
if there are any externally stored columns,
some of them may have already been purged. */
- return(FALSE);
+ return DB_SUCCESS;
}
heap = mem_heap_create(256);
@@ -242,6 +246,10 @@ row_sel_sec_rec_is_for_clust_rec(
thr->prebuilt->m_mysql_table,
record, NULL, NULL, NULL);
+ if (vfield == NULL) {
+ innobase_report_computed_value_failed(row);
+ return DB_COMPUTE_VALUE_FAILED;
+ }
clust_len = vfield->len;
clust_field = static_cast<byte*>(vfield->data);
} else {
@@ -275,7 +283,7 @@ row_sel_sec_rec_is_for_clust_rec(
sec_field, sec_len,
ifield->prefix_len,
clust_index->table)) {
- return FALSE;
+ return DB_SUCCESS;
}
continue;
@@ -311,19 +319,19 @@ row_sel_sec_rec_is_for_clust_rec(
rtr_read_mbr(sec_field, &sec_mbr);
if (!MBR_EQUAL_CMP(&sec_mbr, &tmp_mbr)) {
- return FALSE;
+ return DB_SUCCESS;
}
} else {
if (0 != cmp_data_data(col->mtype, col->prtype,
clust_field, len,
sec_field, sec_len)) {
- return FALSE;
+ return DB_SUCCESS;
}
}
}
- return TRUE;
+ return DB_SUCCESS_LOCKED_REC;
}
/*********************************************************************//**
@@ -890,7 +898,7 @@ row_sel_get_clust_rec(
dict_index_t* index;
rec_t* clust_rec;
rec_t* old_vers;
- dberr_t err;
+ dberr_t err = DB_SUCCESS;
mem_heap_t* heap = NULL;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets = offsets_;
@@ -932,7 +940,7 @@ row_sel_get_clust_rec(
clustered index record did not exist in the read view of
trx. */
- goto func_exit;
+ goto err_exit;
}
offsets = rec_get_offsets(clust_rec, index, offsets, true,
@@ -997,7 +1005,7 @@ row_sel_get_clust_rec(
clust_rec = old_vers;
if (clust_rec == NULL) {
- goto func_exit;
+ goto err_exit;
}
}
@@ -1014,13 +1022,14 @@ row_sel_get_clust_rec(
visit through secondary index records that would not really
exist in our snapshot. */
- if ((old_vers
- || rec_get_deleted_flag(rec, dict_table_is_comp(
- plan->table)))
- && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
- clust_rec, index,
- thr)) {
- goto func_exit;
+ if (old_vers || rec_get_deleted_flag(rec, dict_table_is_comp(
+ plan->table))) {
+ err = row_sel_sec_rec_is_for_clust_rec(rec,
+ plan->index, clust_rec,
+ index, thr);
+ if (err != DB_SUCCESS_LOCKED_REC) {
+ goto err_exit;
+ }
}
}
@@ -1033,7 +1042,6 @@ row_sel_get_clust_rec(
row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
*out_rec = clust_rec;
-func_exit:
err = DB_SUCCESS;
err_exit:
if (UNIV_LIKELY_NULL(heap)) {
@@ -3565,10 +3573,18 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|| trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED
|| dict_index_is_spatial(sec_index)
|| rec_get_deleted_flag(rec, dict_table_is_comp(
- sec_index->table)))
- && !row_sel_sec_rec_is_for_clust_rec(
- rec, sec_index, clust_rec, clust_index, thr)) {
- clust_rec = NULL;
+ sec_index->table)))) {
+ err = row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
+ clust_rec, clust_index, thr);
+ switch (err) {
+ case DB_SUCCESS:
+ clust_rec = NULL;
+ break;
+ case DB_SUCCESS_LOCKED_REC:
+ break;
+ default:
+ goto err_exit;
+ }
}
err = DB_SUCCESS;
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index acc7c02abf2..10156c7d3ab 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -2101,9 +2101,11 @@ row_upd_eval_new_vals(
@param[in,out] node row update node
@param[in] update an update vector if it is update
@param[in] thd mysql thread handle
-@param[in,out] mysql_table mysql table object */
+@param[in,out] mysql_table mysql table object
+@return true if success
+ false if virtual column value computation fails. */
static
-void
+bool
row_upd_store_v_row(
upd_node_t* node,
const upd_t* update,
@@ -2165,24 +2167,33 @@ row_upd_store_v_row(
&mysql_table);
/* Need to compute, this happens when
deleting row */
- innobase_get_computed_value(
- node->row, col, index,
- &vc.heap, node->heap,
- NULL, thd, mysql_table,
- record, NULL, NULL, NULL);
+ dfield_t* vfield =
+ innobase_get_computed_value(
+ node->row, col, index,
+ &vc.heap, node->heap,
+ NULL, thd, mysql_table,
+ record, NULL, NULL,
+ NULL);
+ if (vfield == NULL) {
+ return false;
+ }
}
}
}
}
+
+ return true;
}
/** Stores to the heap the row on which the node->pcur is positioned.
@param[in] node row update node
@param[in] thd mysql thread handle
@param[in,out] mysql_table NULL, or mysql table object when
- user thread invokes dml */
+ user thread invokes dml
+@return false if virtual column value computation fails
+ true otherwise. */
static
-void
+bool
row_upd_store_row(
upd_node_t* node,
THD* thd,
@@ -2226,8 +2237,12 @@ row_upd_store_row(
NULL, NULL, NULL, ext, node->heap);
if (node->table->n_v_cols) {
- row_upd_store_v_row(node, node->is_delete ? NULL : node->update,
+ bool ok = row_upd_store_v_row(node,
+ node->is_delete ? NULL : node->update,
thd, mysql_table);
+ if (!ok) {
+ return false;
+ }
}
if (node->is_delete) {
@@ -2242,6 +2257,7 @@ row_upd_store_row(
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+ return true;
}
/***********************************************************//**
@@ -2957,9 +2973,12 @@ row_upd_del_mark_clust_rec(
/* Store row because we have to build also the secondary index
entries */
- row_upd_store_row(node, trx->mysql_thd,
+ if (!row_upd_store_row(node, trx->mysql_thd,
thr->prebuilt && thr->prebuilt->table == node->table
- ? thr->prebuilt->m_mysql_table : NULL);
+ ? thr->prebuilt->m_mysql_table : NULL)) {
+ err = DB_COMPUTE_VALUE_FAILED;
+ return err;
+ }
/* Mark the clustered index record deleted; we do not have to check
locks, because we assume that we have an x-lock on the record */
@@ -3168,8 +3187,11 @@ row_upd_clust_step(
goto exit_func;
}
- row_upd_store_row(node, trx->mysql_thd,
- thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL);
+ if(!row_upd_store_row(node, trx->mysql_thd,
+ thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL)) {
+ err = DB_COMPUTE_VALUE_FAILED;
+ goto exit_func;
+ }
if (row_upd_changes_ord_field_binary(index, node->update, thr,
node->row, node->ext)) {
diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc
index 047027e4950..2d8704764d1 100644
--- a/storage/innobase/row/row0vers.cc
+++ b/storage/innobase/row/row0vers.cc
@@ -445,9 +445,11 @@ row_vers_must_preserve_del_marked(
@param[in] clust_index clustered index
@param[in] index the secondary index
@param[in] heap heap used to build virtual dtuple
-@param[in,out] vcol_info virtual column information. */
+@param[in,out] vcol_info virtual column information.
+@return true in case of success
+ false if virtual column computation fails */
static
-void
+bool
row_vers_build_clust_v_col(
dtuple_t* row,
dict_index_t* clust_index,
@@ -471,7 +473,8 @@ row_vers_build_clust_v_col(
if (vcol_info && !vcol_info->table()) {
vcol_info->set_table(maria_table);
- return;
+ // wait for second fetch
+ return true;
}
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
@@ -484,12 +487,18 @@ row_vers_build_clust_v_col(
col = reinterpret_cast<const dict_v_col_t*>(
ind_field->col);
- innobase_get_computed_value(
+ dfield_t *vfield = innobase_get_computed_value(
row, col, clust_index, &vc.heap,
heap, NULL, thd, maria_table, record, NULL,
NULL, NULL);
+ if (vfield == NULL) {
+ innobase_report_computed_value_failed(row);
+ ut_ad(0);
+ return false;
+ }
}
}
+ return true;
}
/** Build latest virtual column data from undo log
@@ -826,8 +835,11 @@ row_vers_build_cur_vrow(
mtr->commit();
}
- row_vers_build_clust_v_col(
+ bool res = row_vers_build_clust_v_col(
row, clust_index, index, heap, vcol_info);
+ if (!res) {
+ return NULL;
+ }
if (vcol_info != NULL && vcol_info->is_first_fetch()) {
return NULL;
@@ -948,10 +960,14 @@ row_vers_old_has_index_entry(
mtr->commit();
}
- row_vers_build_clust_v_col(
+ bool res = row_vers_build_clust_v_col(
row, clust_index, index, heap,
vcol_info);
+ if (!res) {
+ goto unsafe_to_purge;
+ }
+
if (vcol_info && vcol_info->is_first_fetch()) {
goto unsafe_to_purge;
}