From 768b9a0ef68b9cf1ff29e46a5a9e0e295da8b8d8 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 7 Jun 2011 19:30:43 +0400 Subject: Bug#11764487: myisam corruption with insert ignore and invalid spatial data Problem: in case of wrong data insert into indexed GEOMETRY fields (e.g. NULL value for a not NULL field) MyISAM reported "ERROR 126 (HY000): Incorrect key file for table; try to repair it" due to misuse of the key deletion function. Fix: always use R-tree key functions for R-tree based indexes and B-tree key functions for B-tree based indexes. mysql-test/r/gis-rtree.result: Bug#11764487: myisam corruption with insert ignore and invalid spatial data - test result. mysql-test/t/gis-rtree.test: Bug#11764487: myisam corruption with insert ignore and invalid spatial data - test case. storage/myisam/mi_update.c: Bug#11764487: myisam corruption with insert ignore and invalid spatial data - handling update errors check for HA_ERR_NULL_IN_SPATIAL as well to be consistent with mi_write(); - always use keyinfo->ck_delete()/ck_insert() instead of _mi_ck_delete()/_mi_ck_write() to handle index properly, as it may be of B-tree or R-tree type. storage/myisam/mi_write.c: Bug#11764487: myisam corruption with insert ignore and invalid spatial data - always use keyinfo->ck_delete() instead of _mi_ck_delete() to handle index properly, as it may be of B-tree or R-tree type. --- mysql-test/r/gis-rtree.result | 27 +++++++++++++++++++++++++++ mysql-test/t/gis-rtree.test | 28 ++++++++++++++++++++++++++++ storage/myisam/mi_update.c | 9 +++++---- storage/myisam/mi_write.c | 2 +- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index eb9c350f589..1f6d6fa851e 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -1549,3 +1549,30 @@ HANDLER t1 READ a NEXT; HANDLER t1 CLOSE; DROP TABLE t1; End of 5.0 tests. +# +# Bug #57323/11764487: myisam corruption with insert ignore +# and invalid spatial data +# +CREATE TABLE t1(a LINESTRING NOT NULL, b GEOMETRY NOT NULL, +SPATIAL KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(GEOMFROMTEXT("point (0 0)"), GEOMFROMTEXT("point (1 1)")); +INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=GEOMFROMTEXT("error"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=NULL; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +SELECT ASTEXT(a), ASTEXT(b) FROM t1; +ASTEXT(a) ASTEXT(b) +POINT(0 0) POINT(1 1) +DROP TABLE t1; +CREATE TABLE t1(a INT NOT NULL, b GEOMETRY NOT NULL, +KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(0, GEOMFROMTEXT("point (1 1)")); +INSERT IGNORE INTO t1 SET a=0, b=GEOMFROMTEXT("error"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +INSERT IGNORE INTO t1 SET a=1, b=NULL; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +SELECT a, ASTEXT(b) FROM t1; +a ASTEXT(b) +0 POINT(1 1) +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index b006096528e..e7e6fa59df0 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -928,3 +928,31 @@ DROP TABLE t1; --echo End of 5.0 tests. + + +--echo # +--echo # Bug #57323/11764487: myisam corruption with insert ignore +--echo # and invalid spatial data +--echo # + +CREATE TABLE t1(a LINESTRING NOT NULL, b GEOMETRY NOT NULL, + SPATIAL KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(GEOMFROMTEXT("point (0 0)"), GEOMFROMTEXT("point (1 1)")); +--error ER_CANT_CREATE_GEOMETRY_OBJECT +INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=GEOMFROMTEXT("error"); +--error ER_CANT_CREATE_GEOMETRY_OBJECT +INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=NULL; +SELECT ASTEXT(a), ASTEXT(b) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1(a INT NOT NULL, b GEOMETRY NOT NULL, + KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM; +INSERT INTO t1 VALUES(0, GEOMFROMTEXT("point (1 1)")); +--error ER_CANT_CREATE_GEOMETRY_OBJECT +INSERT IGNORE INTO t1 SET a=0, b=GEOMFROMTEXT("error"); +--error ER_CANT_CREATE_GEOMETRY_OBJECT +INSERT IGNORE INTO t1 SET a=1, b=NULL; +SELECT a, ASTEXT(b) FROM t1; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/storage/myisam/mi_update.c b/storage/myisam/mi_update.c index a18bb5f1443..c767fa44ed5 100644 --- a/storage/myisam/mi_update.c +++ b/storage/myisam/mi_update.c @@ -193,8 +193,8 @@ err: save_errno=my_errno; if (changed) key_changed|= HA_STATE_CHANGED; - if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM || - my_errno == HA_ERR_RECORD_FILE_FULL) + if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL || + my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM) { info->errkey= (int) i; flag=0; @@ -212,8 +212,9 @@ err: { uint new_length=_mi_make_key(info,i,new_key,newrec,pos); uint old_length= _mi_make_key(info,i,old_key,oldrec,pos); - if ((flag++ && _mi_ck_delete(info,i,new_key,new_length)) || - _mi_ck_write(info,i,old_key,old_length)) + if ((flag++ && + share->keyinfo[i].ck_delete(info, i, new_key, new_length)) || + share->keyinfo[i].ck_insert(info, i, old_key, old_length)) break; } } diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index 3c8ebe5dbd8..51ae06b117d 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -211,7 +211,7 @@ err: else { uint key_length=_mi_make_key(info,i,buff,record,filepos); - if (_mi_ck_delete(info,i,buff,key_length)) + if (share->keyinfo[i].ck_delete(info, i, buff, key_length)) { if (local_lock_tree) rw_unlock(&share->key_root_lock[i]); -- cgit v1.2.1