mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-29753 An error is wrongly reported during INSERT with vcol index
See also commits aa8a31da
and 64678c for a Bug #22990029 fix.
In this scenario INSERT chose to check if delete unmarking is available for
a just deleted record. To build an update vector, it needed to calculate
the vcols as well. Since this INSERT was not IGNORE-flagged, recalculation
failed.
Solutiuon: temporarily set abort_on_warning=true, while calculating the
column for delete-unmarked insert.
This commit is contained in:
@@ -249,12 +249,15 @@ ENGINE=InnoDB;
|
|||||||
INSERT IGNORE INTO t1 (a,b) VALUES(1,20190132);
|
INSERT IGNORE INTO t1 (a,b) VALUES(1,20190132);
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1265 Data truncated for column 'vb' at row 1
|
Warning 1265 Data truncated for column 'vb' at row 1
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b vb
|
||||||
|
1 20190132 0000-00-00
|
||||||
BEGIN;
|
BEGIN;
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
INSERT INTO t1 (a,b) VALUES(1,20190123);
|
INSERT INTO t1 (a,b) VALUES(1,20190123);
|
||||||
ERROR 22007: Incorrect date value: '20190132' for column `test`.`t1`.`vb` at row 1
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
a b vb
|
a b vb
|
||||||
|
1 20190123 2019-01-23
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
a b vb
|
a b vb
|
||||||
@@ -340,4 +343,33 @@ Warnings:
|
|||||||
Warning 1365 Division by 0
|
Warning 1365 Division by 0
|
||||||
disconnect stop_purge;
|
disconnect stop_purge;
|
||||||
DROP TABLE t, t_odd;
|
DROP TABLE t, t_odd;
|
||||||
|
#
|
||||||
|
# MDEV-29753 An error is wrongly reported during INSERT with vcol index
|
||||||
|
# See also Bug #22990029
|
||||||
|
#
|
||||||
|
CREATE TABLE t(pk INT PRIMARY KEY,
|
||||||
|
fld1 INT NOT NULL,
|
||||||
|
fld2 INT AS (100/fld1) VIRTUAL,
|
||||||
|
KEY(fld1), KEY(fld2));
|
||||||
|
INSERT IGNORE t(pk, fld1) VALUES(1, 0);
|
||||||
|
Warnings:
|
||||||
|
Warning 1365 Division by 0
|
||||||
|
SELECT * FROM t;
|
||||||
|
pk fld1 fld2
|
||||||
|
1 0 NULL
|
||||||
|
Warnings:
|
||||||
|
Warning 1365 Division by 0
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t;
|
||||||
|
Warnings:
|
||||||
|
Warning 1365 Division by 0
|
||||||
|
Warning 1365 Division by 0
|
||||||
|
Warning 1365 Division by 0
|
||||||
|
INSERT INTO t (pk, fld1) VALUES(1,1);
|
||||||
|
SELECT * FROM t;
|
||||||
|
pk fld1 fld2
|
||||||
|
1 1 100
|
||||||
|
# Cleanup
|
||||||
|
ROLLBACK;
|
||||||
|
DROP TABLE t;
|
||||||
# End of 10.3 tests
|
# End of 10.3 tests
|
||||||
|
@@ -275,9 +275,9 @@ DROP TABLE t1;
|
|||||||
CREATE TABLE t1(a INT PRIMARY KEY, b INT, vb DATE AS(b) VIRTUAL, KEY(vb))
|
CREATE TABLE t1(a INT PRIMARY KEY, b INT, vb DATE AS(b) VIRTUAL, KEY(vb))
|
||||||
ENGINE=InnoDB;
|
ENGINE=InnoDB;
|
||||||
INSERT IGNORE INTO t1 (a,b) VALUES(1,20190132);
|
INSERT IGNORE INTO t1 (a,b) VALUES(1,20190132);
|
||||||
|
SELECT * FROM t1;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
--error ER_TRUNCATED_WRONG_VALUE
|
|
||||||
INSERT INTO t1 (a,b) VALUES(1,20190123);
|
INSERT INTO t1 (a,b) VALUES(1,20190123);
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@@ -361,5 +361,24 @@ SELECT fld2 FROM t FORCE INDEX(fld1);
|
|||||||
--disconnect stop_purge
|
--disconnect stop_purge
|
||||||
DROP TABLE t, t_odd;
|
DROP TABLE t, t_odd;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-29753 An error is wrongly reported during INSERT with vcol index
|
||||||
|
--echo # See also Bug #22990029
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t(pk INT PRIMARY KEY,
|
||||||
|
fld1 INT NOT NULL,
|
||||||
|
fld2 INT AS (100/fld1) VIRTUAL,
|
||||||
|
KEY(fld1), KEY(fld2));
|
||||||
|
INSERT IGNORE t(pk, fld1) VALUES(1, 0);
|
||||||
|
SELECT * FROM t;
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM t;
|
||||||
|
INSERT INTO t (pk, fld1) VALUES(1,1);
|
||||||
|
SELECT * FROM t;
|
||||||
|
|
||||||
|
--echo # Cleanup
|
||||||
|
ROLLBACK;
|
||||||
|
DROP TABLE t;
|
||||||
|
|
||||||
--echo # End of 10.3 tests
|
--echo # End of 10.3 tests
|
||||||
|
17
sql/table.cc
17
sql/table.cc
@@ -8158,9 +8158,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
|
|||||||
/*
|
/*
|
||||||
Calculate the virtual field value for a specified field.
|
Calculate the virtual field value for a specified field.
|
||||||
@param vf A field to calculate
|
@param vf A field to calculate
|
||||||
@param ignore_warnings Ignore calculation warnings. This usually
|
@param ignore_warnings Ignore the warnings and also make the
|
||||||
means that a calculation is internal and is
|
calculations permissive. This usually means
|
||||||
not expected to fail.
|
that a calculation is internal and is not
|
||||||
|
expected to fail.
|
||||||
*/
|
*/
|
||||||
int TABLE::update_virtual_field(Field *vf, bool ignore_warnings)
|
int TABLE::update_virtual_field(Field *vf, bool ignore_warnings)
|
||||||
{
|
{
|
||||||
@@ -8169,8 +8170,13 @@ int TABLE::update_virtual_field(Field *vf, bool ignore_warnings)
|
|||||||
Counting_error_handler count_errors;
|
Counting_error_handler count_errors;
|
||||||
Suppress_warnings_error_handler warning_handler;
|
Suppress_warnings_error_handler warning_handler;
|
||||||
in_use->push_internal_handler(&count_errors);
|
in_use->push_internal_handler(&count_errors);
|
||||||
|
bool abort_on_warning;
|
||||||
if (ignore_warnings)
|
if (ignore_warnings)
|
||||||
|
{
|
||||||
|
abort_on_warning= in_use->abort_on_warning;
|
||||||
|
in_use->abort_on_warning= false;
|
||||||
in_use->push_internal_handler(&warning_handler);
|
in_use->push_internal_handler(&warning_handler);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
TODO: this may impose memory leak until table flush.
|
TODO: this may impose memory leak until table flush.
|
||||||
See comment in
|
See comment in
|
||||||
@@ -8183,7 +8189,12 @@ int TABLE::update_virtual_field(Field *vf, bool ignore_warnings)
|
|||||||
in_use->restore_active_arena(expr_arena, &backup_arena);
|
in_use->restore_active_arena(expr_arena, &backup_arena);
|
||||||
in_use->pop_internal_handler();
|
in_use->pop_internal_handler();
|
||||||
if (ignore_warnings)
|
if (ignore_warnings)
|
||||||
|
{
|
||||||
|
in_use->abort_on_warning= abort_on_warning;
|
||||||
in_use->pop_internal_handler();
|
in_use->pop_internal_handler();
|
||||||
|
// This is an internal calculation, we expect it to always succeed
|
||||||
|
DBUG_ASSERT(count_errors.errors == 0);
|
||||||
|
}
|
||||||
DBUG_RETURN(count_errors.errors);
|
DBUG_RETURN(count_errors.errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -215,6 +215,8 @@ the equal ordering fields. NOTE: we compare the fields as binary strings!
|
|||||||
@param[in] offsets rec_get_offsets(rec,index), or NULL
|
@param[in] offsets rec_get_offsets(rec,index), or NULL
|
||||||
@param[in] no_sys skip the system columns
|
@param[in] no_sys skip the system columns
|
||||||
DB_TRX_ID and DB_ROLL_PTR
|
DB_TRX_ID and DB_ROLL_PTR
|
||||||
|
@param[in] ignore_warnings ignore warnings during vcol calculation, which
|
||||||
|
means that this calculation is internal only
|
||||||
@param[in] trx transaction (for diagnostics),
|
@param[in] trx transaction (for diagnostics),
|
||||||
or NULL
|
or NULL
|
||||||
@param[in] heap memory heap from which allocated
|
@param[in] heap memory heap from which allocated
|
||||||
@@ -230,11 +232,12 @@ row_upd_build_difference_binary(
|
|||||||
const rec_t* rec,
|
const rec_t* rec,
|
||||||
const rec_offs* offsets,
|
const rec_offs* offsets,
|
||||||
bool no_sys,
|
bool no_sys,
|
||||||
|
bool ignore_warnings,
|
||||||
trx_t* trx,
|
trx_t* trx,
|
||||||
mem_heap_t* heap,
|
mem_heap_t* heap,
|
||||||
TABLE* mysql_table,
|
TABLE* mysql_table,
|
||||||
dberr_t* error)
|
dberr_t* error)
|
||||||
MY_ATTRIBUTE((nonnull(1,2,3,7,9), warn_unused_result));
|
MY_ATTRIBUTE((nonnull(1,2,3,8,10), warn_unused_result));
|
||||||
/** Apply an update vector to an index entry.
|
/** Apply an update vector to an index entry.
|
||||||
@param[in,out] entry index entry to be updated; the clustered index record
|
@param[in,out] entry index entry to be updated; the clustered index record
|
||||||
must be covered by a lock or a page latch to prevent
|
must be covered by a lock or a page latch to prevent
|
||||||
|
@@ -307,7 +307,7 @@ row_ins_clust_index_entry_by_modify(
|
|||||||
}
|
}
|
||||||
|
|
||||||
update = row_upd_build_difference_binary(
|
update = row_upd_build_difference_binary(
|
||||||
cursor->index, entry, rec, NULL, true,
|
cursor->index, entry, rec, NULL, true, true,
|
||||||
thr_get_trx(thr), heap, mysql_table, &err);
|
thr_get_trx(thr), heap, mysql_table, &err);
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
return(err);
|
return(err);
|
||||||
|
@@ -2248,7 +2248,7 @@ func_exit_committed:
|
|||||||
row, NULL, index, heap, ROW_BUILD_NORMAL);
|
row, NULL, index, heap, ROW_BUILD_NORMAL);
|
||||||
upd_t* update = row_upd_build_difference_binary(
|
upd_t* update = row_upd_build_difference_binary(
|
||||||
index, entry, btr_pcur_get_rec(&pcur), cur_offsets,
|
index, entry, btr_pcur_get_rec(&pcur), cur_offsets,
|
||||||
false, NULL, heap, dup->table, &error);
|
false, false, NULL, heap, dup->table, &error);
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
@@ -1044,6 +1044,7 @@ row_upd_build_difference_binary(
|
|||||||
const rec_t* rec,
|
const rec_t* rec,
|
||||||
const rec_offs* offsets,
|
const rec_offs* offsets,
|
||||||
bool no_sys,
|
bool no_sys,
|
||||||
|
bool ignore_warnings,
|
||||||
trx_t* trx,
|
trx_t* trx,
|
||||||
mem_heap_t* heap,
|
mem_heap_t* heap,
|
||||||
TABLE* mysql_table,
|
TABLE* mysql_table,
|
||||||
@@ -1153,7 +1154,7 @@ row_upd_build_difference_binary(
|
|||||||
dfield_t* vfield = innobase_get_computed_value(
|
dfield_t* vfield = innobase_get_computed_value(
|
||||||
update->old_vrow, col, index,
|
update->old_vrow, col, index,
|
||||||
&vc.heap, heap, NULL, thd, mysql_table, record,
|
&vc.heap, heap, NULL, thd, mysql_table, record,
|
||||||
NULL, NULL);
|
NULL, NULL, ignore_warnings);
|
||||||
if (vfield == NULL) {
|
if (vfield == NULL) {
|
||||||
*error = DB_COMPUTE_VALUE_FAILED;
|
*error = DB_COMPUTE_VALUE_FAILED;
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
Reference in New Issue
Block a user