Commit 97db6c15 authored by Nikita Malyavin's avatar Nikita Malyavin

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.
parent a3d66090
...@@ -747,4 +747,66 @@ ANALYZE TABLE t1, t2; ...@@ -747,4 +747,66 @@ ANALYZE TABLE t1, t2;
--eval $query --eval $query
DROP TABLE t1, t2; 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 # --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;
}
...@@ -825,6 +825,56 @@ a1 a2 b ...@@ -825,6 +825,56 @@ a1 a2 b
0 NULL 1 0 NULL 1
DROP TABLE t1, t2; 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 # BUG#21365158 WL8149:ASSERTION `!TABLE || (!TABLE->WRITE_SET
# #
......
...@@ -827,6 +827,56 @@ a1 a2 b ...@@ -827,6 +827,56 @@ a1 a2 b
0 NULL 1 0 NULL 1
DROP TABLE t1, t2; 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 VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2,t3; DROP TABLE IF EXISTS t1,t2,t3;
DROP PROCEDURE IF EXISTS p1; DROP PROCEDURE IF EXISTS p1;
......
...@@ -456,8 +456,7 @@ select pk, col_bit+0, vcol_bit+0 from t1; ...@@ -456,8 +456,7 @@ select pk, col_bit+0, vcol_bit+0 from t1;
pk col_bit+0 vcol_bit+0 pk col_bit+0 vcol_bit+0
99 10000 1023 99 10000 1023
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99); REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
Warnings: ERROR 22001: Data too long for column 'vcol_bit' at row 1
Warning 1264 Out of range value for column 'vcol_bit' at row 1
drop table t1; drop table t1;
# #
# MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status() # 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); ...@@ -476,8 +475,7 @@ INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
Warnings: Warnings:
Warning 1264 Out of range value for column 'vi' at row 1 Warning 1264 Out of range value for column 'vi' at row 1
REPLACE INTO t1 (pk,i) VALUES (1,2); REPLACE INTO t1 (pk,i) VALUES (1,2);
Warnings: ERROR 22003: Out of range value for column 'vi' at row 1
Warning 1264 Out of range value for column 'vi' at row 1
DROP TABLE t1; DROP TABLE t1;
SET @sql_mode=@old_sql_mode; SET @sql_mode=@old_sql_mode;
# #
......
...@@ -431,6 +431,7 @@ replace INTO `t1` (`pk`,col_bit) VALUES (99,1000); ...@@ -431,6 +431,7 @@ replace INTO `t1` (`pk`,col_bit) VALUES (99,1000);
select pk, col_bit+0, vcol_bit+0 from t1; select pk, col_bit+0, vcol_bit+0 from t1;
replace INTO `t1` (`pk`,col_bit) VALUES (99,10000); replace INTO `t1` (`pk`,col_bit) VALUES (99,10000);
select pk, col_bit+0, vcol_bit+0 from t1; select pk, col_bit+0, vcol_bit+0 from t1;
--error ER_DATA_TOO_LONG
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99); REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
drop table t1; drop table t1;
...@@ -451,6 +452,7 @@ CREATE TABLE t1 ( ...@@ -451,6 +452,7 @@ CREATE TABLE t1 (
INSERT INTO t1 (pk,i) VALUES (1,1); INSERT INTO t1 (pk,i) VALUES (1,1);
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
INSERT IGNORE INTO t1 (pk,i) VALUES (1,127); INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
--error ER_WARN_DATA_OUT_OF_RANGE
REPLACE INTO t1 (pk,i) VALUES (1,2); REPLACE INTO t1 (pk,i) VALUES (1,2);
DROP TABLE t1; DROP TABLE t1;
SET @sql_mode=@old_sql_mode; SET @sql_mode=@old_sql_mode;
......
...@@ -1748,15 +1748,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1748,15 +1748,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
} }
if (table->vfield) if (table->vfield)
{ {
my_bool abort_on_warning= thd->abort_on_warning;
/* /*
We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ) We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ)
in handler methods for the just read row in record[1]. in handler methods for the just read row in record[1].
*/ */
table->move_fields(table->field, table->record[1], table->record[0]); table->move_fields(table->field, table->record[1], table->record[0]);
thd->abort_on_warning= 0; if (table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE))
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE); goto err;
thd->abort_on_warning= abort_on_warning;
table->move_fields(table->field, table->record[0], table->record[1]); table->move_fields(table->field, table->record[0], table->record[1]);
} }
if (info->handle_duplicates == DUP_UPDATE) if (info->handle_duplicates == DUP_UPDATE)
......
...@@ -103,6 +103,7 @@ this program; if not, write to the Free Software Foundation, Inc., ...@@ -103,6 +103,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include "srv0mon.h" #include "srv0mon.h"
#include "srv0srv.h" #include "srv0srv.h"
#include "srv0start.h" #include "srv0start.h"
#include "rem0rec.h"
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
#include "trx0purge.h" #include "trx0purge.h"
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
...@@ -21881,6 +21882,13 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage) ...@@ -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. /** Get the computed value by supplying the base column values.
@param[in,out] row the data row @param[in,out] row the data row
@param[in] col virtual column @param[in] col virtual column
...@@ -22008,13 +22016,6 @@ innobase_get_computed_value( ...@@ -22008,13 +22016,6 @@ innobase_get_computed_value(
dbug_tmp_restore_column_map(mysql_table->write_set, old_write_set); dbug_tmp_restore_column_map(mysql_table->write_set, old_write_set);
if (ret != 0) { 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); DBUG_RETURN(NULL);
} }
......
...@@ -874,6 +874,12 @@ class ib_vcol_row ...@@ -874,6 +874,12 @@ class ib_vcol_row
} }
}; };
/** 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. /** Get the computed value by supplying the base column values.
@param[in,out] row the data row @param[in,out] row the data row
@param[in] col virtual column @param[in] col virtual column
......
...@@ -154,11 +154,15 @@ fields are compared with collation! ...@@ -154,11 +154,15 @@ fields are compared with collation!
must be protected by a page s-latch must be protected by a page s-latch
@param[in] clust_index clustered index @param[in] clust_index clustered index
@param[in] thr query thread @param[in] thr query thread
@return TRUE if the secondary record is equal to the corresponding @retval DB_COMPUTE_VALUE_FAILED in case of virtual column value computation
fields in the clustered record, when compared with collation; failure.
FALSE if not equal or if the clustered record has been marked for deletion */ @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 static
ibool dberr_t
row_sel_sec_rec_is_for_clust_rec( row_sel_sec_rec_is_for_clust_rec(
const rec_t* sec_rec, const rec_t* sec_rec,
dict_index_t* sec_index, dict_index_t* sec_index,
...@@ -190,7 +194,7 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -190,7 +194,7 @@ row_sel_sec_rec_is_for_clust_rec(
it is not visible in the read view. Besides, it is not visible in the read view. Besides,
if there are any externally stored columns, if there are any externally stored columns,
some of them may have already been purged. */ some of them may have already been purged. */
return(FALSE); return DB_SUCCESS;
} }
heap = mem_heap_create(256); heap = mem_heap_create(256);
...@@ -242,6 +246,10 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -242,6 +246,10 @@ row_sel_sec_rec_is_for_clust_rec(
thr->prebuilt->m_mysql_table, thr->prebuilt->m_mysql_table,
record, NULL, NULL, NULL); record, NULL, NULL, NULL);
if (vfield == NULL) {
innobase_report_computed_value_failed(row);
return DB_COMPUTE_VALUE_FAILED;
}
clust_len = vfield->len; clust_len = vfield->len;
clust_field = static_cast<byte*>(vfield->data); clust_field = static_cast<byte*>(vfield->data);
} else { } else {
...@@ -275,7 +283,7 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -275,7 +283,7 @@ row_sel_sec_rec_is_for_clust_rec(
sec_field, sec_len, sec_field, sec_len,
ifield->prefix_len, ifield->prefix_len,
clust_index->table)) { clust_index->table)) {
return FALSE; return DB_SUCCESS;
} }
continue; continue;
...@@ -311,19 +319,19 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -311,19 +319,19 @@ row_sel_sec_rec_is_for_clust_rec(
rtr_read_mbr(sec_field, &sec_mbr); rtr_read_mbr(sec_field, &sec_mbr);
if (!MBR_EQUAL_CMP(&sec_mbr, &tmp_mbr)) { if (!MBR_EQUAL_CMP(&sec_mbr, &tmp_mbr)) {
return FALSE; return DB_SUCCESS;
} }
} else { } else {
if (0 != cmp_data_data(col->mtype, col->prtype, if (0 != cmp_data_data(col->mtype, col->prtype,
clust_field, len, clust_field, len,
sec_field, sec_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( ...@@ -890,7 +898,7 @@ row_sel_get_clust_rec(
dict_index_t* index; dict_index_t* index;
rec_t* clust_rec; rec_t* clust_rec;
rec_t* old_vers; rec_t* old_vers;
dberr_t err; dberr_t err = DB_SUCCESS;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets = offsets_; rec_offs* offsets = offsets_;
...@@ -932,7 +940,7 @@ row_sel_get_clust_rec( ...@@ -932,7 +940,7 @@ row_sel_get_clust_rec(
clustered index record did not exist in the read view of clustered index record did not exist in the read view of
trx. */ trx. */
goto func_exit; goto err_exit;
} }
offsets = rec_get_offsets(clust_rec, index, offsets, true, offsets = rec_get_offsets(clust_rec, index, offsets, true,
...@@ -997,7 +1005,7 @@ row_sel_get_clust_rec( ...@@ -997,7 +1005,7 @@ row_sel_get_clust_rec(
clust_rec = old_vers; clust_rec = old_vers;
if (clust_rec == NULL) { if (clust_rec == NULL) {
goto func_exit; goto err_exit;
} }
} }
...@@ -1014,13 +1022,14 @@ row_sel_get_clust_rec( ...@@ -1014,13 +1022,14 @@ row_sel_get_clust_rec(
visit through secondary index records that would not really visit through secondary index records that would not really
exist in our snapshot. */ exist in our snapshot. */
if ((old_vers if (old_vers || rec_get_deleted_flag(rec, dict_table_is_comp(
|| rec_get_deleted_flag(rec, dict_table_is_comp( plan->table))) {
plan->table))) err = row_sel_sec_rec_is_for_clust_rec(rec,
&& !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, plan->index, clust_rec,
clust_rec, index, index, thr);
thr)) { if (err != DB_SUCCESS_LOCKED_REC) {
goto func_exit; goto err_exit;
}
} }
} }
...@@ -1033,7 +1042,6 @@ row_sel_get_clust_rec( ...@@ -1033,7 +1042,6 @@ row_sel_get_clust_rec(
row_sel_fetch_columns(index, clust_rec, offsets, row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns)); UT_LIST_GET_FIRST(plan->columns));
*out_rec = clust_rec; *out_rec = clust_rec;
func_exit:
err = DB_SUCCESS; err = DB_SUCCESS;
err_exit: err_exit:
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
...@@ -3565,10 +3573,18 @@ Row_sel_get_clust_rec_for_mysql::operator()( ...@@ -3565,10 +3573,18 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|| trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED || trx->isolation_level <= TRX_ISO_READ_UNCOMMITTED
|| dict_index_is_spatial(sec_index) || dict_index_is_spatial(sec_index)
|| rec_get_deleted_flag(rec, dict_table_is_comp( || rec_get_deleted_flag(rec, dict_table_is_comp(
sec_index->table))) sec_index->table)))) {
&& !row_sel_sec_rec_is_for_clust_rec( err = row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
rec, sec_index, clust_rec, clust_index, thr)) { clust_rec, clust_index, thr);
switch (err) {
case DB_SUCCESS:
clust_rec = NULL; clust_rec = NULL;
break;
case DB_SUCCESS_LOCKED_REC:
break;
default:
goto err_exit;
}
} }
err = DB_SUCCESS; err = DB_SUCCESS;
......
...@@ -2101,9 +2101,11 @@ row_upd_eval_new_vals( ...@@ -2101,9 +2101,11 @@ row_upd_eval_new_vals(
@param[in,out] node row update node @param[in,out] node row update node
@param[in] update an update vector if it is update @param[in] update an update vector if it is update
@param[in] thd mysql thread handle @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 static
void bool
row_upd_store_v_row( row_upd_store_v_row(
upd_node_t* node, upd_node_t* node,
const upd_t* update, const upd_t* update,
...@@ -2165,24 +2167,33 @@ row_upd_store_v_row( ...@@ -2165,24 +2167,33 @@ row_upd_store_v_row(
&mysql_table); &mysql_table);
/* Need to compute, this happens when /* Need to compute, this happens when
deleting row */ deleting row */
dfield_t* vfield =
innobase_get_computed_value( innobase_get_computed_value(
node->row, col, index, node->row, col, index,
&vc.heap, node->heap, &vc.heap, node->heap,
NULL, thd, mysql_table, NULL, thd, mysql_table,
record, NULL, NULL, NULL); record, NULL, NULL,
NULL);
if (vfield == NULL) {
return false;
} }
} }
} }
} }
}
return true;
} }
/** Stores to the heap the row on which the node->pcur is positioned. /** Stores to the heap the row on which the node->pcur is positioned.
@param[in] node row update node @param[in] node row update node
@param[in] thd mysql thread handle @param[in] thd mysql thread handle
@param[in,out] mysql_table NULL, or mysql table object when @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 static
void bool
row_upd_store_row( row_upd_store_row(
upd_node_t* node, upd_node_t* node,
THD* thd, THD* thd,
...@@ -2226,8 +2237,12 @@ row_upd_store_row( ...@@ -2226,8 +2237,12 @@ row_upd_store_row(
NULL, NULL, NULL, ext, node->heap); NULL, NULL, NULL, ext, node->heap);
if (node->table->n_v_cols) { 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); thd, mysql_table);
if (!ok) {
return false;
}
} }
if (node->is_delete) { if (node->is_delete) {
...@@ -2242,6 +2257,7 @@ row_upd_store_row( ...@@ -2242,6 +2257,7 @@ row_upd_store_row(
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
} }
return true;
} }
/***********************************************************//** /***********************************************************//**
...@@ -2957,9 +2973,12 @@ row_upd_del_mark_clust_rec( ...@@ -2957,9 +2973,12 @@ row_upd_del_mark_clust_rec(
/* Store row because we have to build also the secondary index /* Store row because we have to build also the secondary index
entries */ 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 && 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 /* 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 */ locks, because we assume that we have an x-lock on the record */
...@@ -3168,8 +3187,11 @@ row_upd_clust_step( ...@@ -3168,8 +3187,11 @@ row_upd_clust_step(
goto exit_func; goto exit_func;
} }
row_upd_store_row(node, trx->mysql_thd, if(!row_upd_store_row(node, trx->mysql_thd,
thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL); 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, if (row_upd_changes_ord_field_binary(index, node->update, thr,
node->row, node->ext)) { node->row, node->ext)) {
......
...@@ -445,9 +445,11 @@ row_vers_must_preserve_del_marked( ...@@ -445,9 +445,11 @@ row_vers_must_preserve_del_marked(
@param[in] clust_index clustered index @param[in] clust_index clustered index
@param[in] index the secondary index @param[in] index the secondary index
@param[in] heap heap used to build virtual dtuple @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 static
void bool
row_vers_build_clust_v_col( row_vers_build_clust_v_col(
dtuple_t* row, dtuple_t* row,
dict_index_t* clust_index, dict_index_t* clust_index,
...@@ -471,7 +473,8 @@ row_vers_build_clust_v_col( ...@@ -471,7 +473,8 @@ row_vers_build_clust_v_col(
if (vcol_info && !vcol_info->table()) { if (vcol_info && !vcol_info->table()) {
vcol_info->set_table(maria_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++) { for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
...@@ -484,12 +487,18 @@ row_vers_build_clust_v_col( ...@@ -484,12 +487,18 @@ row_vers_build_clust_v_col(
col = reinterpret_cast<const dict_v_col_t*>( col = reinterpret_cast<const dict_v_col_t*>(
ind_field->col); ind_field->col);
innobase_get_computed_value( dfield_t *vfield = innobase_get_computed_value(
row, col, clust_index, &vc.heap, row, col, clust_index, &vc.heap,
heap, NULL, thd, maria_table, record, NULL, heap, NULL, thd, maria_table, record, NULL,
NULL, 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 /** Build latest virtual column data from undo log
...@@ -826,8 +835,11 @@ row_vers_build_cur_vrow( ...@@ -826,8 +835,11 @@ row_vers_build_cur_vrow(
mtr->commit(); mtr->commit();
} }
row_vers_build_clust_v_col( bool res = row_vers_build_clust_v_col(
row, clust_index, index, heap, vcol_info); row, clust_index, index, heap, vcol_info);
if (!res) {
return NULL;
}
if (vcol_info != NULL && vcol_info->is_first_fetch()) { if (vcol_info != NULL && vcol_info->is_first_fetch()) {
return NULL; return NULL;
...@@ -948,10 +960,14 @@ row_vers_old_has_index_entry( ...@@ -948,10 +960,14 @@ row_vers_old_has_index_entry(
mtr->commit(); mtr->commit();
} }
row_vers_build_clust_v_col( bool res = row_vers_build_clust_v_col(
row, clust_index, index, heap, row, clust_index, index, heap,
vcol_info); vcol_info);
if (!res) {
goto unsafe_to_purge;
}
if (vcol_info && vcol_info->is_first_fetch()) { if (vcol_info && vcol_info->is_first_fetch()) {
goto unsafe_to_purge; goto unsafe_to_purge;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment