Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PS-9121 Innodb fails to update spatial index #5277

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions mysql-test/suite/innodb_gis/r/gis_precision.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Create separate tables of supported geometric types
CREATE TABLE gis_point (
id INTEGER NOT NULL PRIMARY KEY,
shape POINT NOT NULL SRID 0,
SPATIAL KEY IND(shape)
) ENGINE=INNODB;
CREATE TABLE gis_line (
id INTEGER NOT NULL PRIMARY KEY,
shape LINESTRING NOT NULL SRID 0,
SPATIAL KEY IND(shape)
) ENGINE=INNODB;
CREATE TABLE gis_polygon(
id INTEGER NOT NULL PRIMARY KEY,
shape POLYGON NOT NULL SRID 0,
SPATIAL KEY IND(shape)
) ENGINE=INNODB;
Point
INSERT INTO gis_point VALUES (1,POINT(0.0000000000000099,0));
SELECT id, ST_AsText(shape) FROM gis_point;
id ST_AsText(shape)
1 POINT(0.0000000000000099 0)
UPDATE gis_point SET shape = POINT(0.00000000000001, 0) WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_point;
id ST_AsText(shape)
1 POINT(0.00000000000001 0)
DELETE FROM gis_point WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_point;
id ST_AsText(shape)
INSERT INTO gis_point VALUES (1,POINT(0.0000000000000099,0));
SELECT id, ST_AsText(shape) FROM gis_point;
id ST_AsText(shape)
1 POINT(0.0000000000000099 0)
Line
INSERT INTO gis_line VALUES
(1, ST_LineFromText('LINESTRING(0.0000000000000099 0,1 0.0000000000000099)'));
SELECT id, ST_AsText(shape) FROM gis_line;
id ST_AsText(shape)
1 LINESTRING(0.0000000000000099 0,1 0.0000000000000099)
UPDATE gis_line SET shape = ST_LineFromText('LINESTRING(0.00000000000001 0,1 0.00000000000001)') WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_line;
id ST_AsText(shape)
1 LINESTRING(0.00000000000001 0,1 0.00000000000001)
DELETE FROM gis_line WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_line;
id ST_AsText(shape)
INSERT INTO gis_line VALUES (1, ST_LineFromText('LINESTRING(0.0000000000000099 0,1 0.0000000000000099)'));
SELECT id, ST_AsText(shape) FROM gis_line;
id ST_AsText(shape)
1 LINESTRING(0.0000000000000099 0,1 0.0000000000000099)
Polygon
INSERT INTO gis_polygon VALUES
(1, ST_PolyFromText('POLYGON((-0.1681156881122417 47.54646568683867,-0.031445000320673 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.0318659991025925 47.310115814208984,-0.1681156881122417 47.54646568683867))'));
SELECT id, ST_AsText(shape) FROM gis_polygon;
id ST_AsText(shape)
1 POLYGON((-0.1681156881122417 47.54646568683867,-0.031445000320673 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.0318659991025925 47.310115814208984,-0.1681156881122417 47.54646568683867))
UPDATE gis_polygon SET
shape = ST_PolyFromText('POLYGON((-0.168115688112241675 47.54646568683867,-0.03144500032067299 47.88496876305664,-0.849334763684143234 47.31022644042969,-0.03186599910259247 47.310115814208984,-0.168115688112241675 47.54646568683867))')
WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_polygon;
id ST_AsText(shape)
1 POLYGON((-0.16811568811224167 47.54646568683867,-0.03144500032067299 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.03186599910259247 47.310115814208984,-0.16811568811224167 47.54646568683867))
DELETE FROM gis_polygon WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_polygon;
id ST_AsText(shape)
INSERT INTO gis_polygon VALUES
(1, ST_PolyFromText('POLYGON((-0.1681156881122417 47.54646568683867,-0.031445000320673 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.0318659991025925 47.310115814208984,-0.1681156881122417 47.54646568683867))'));
SELECT id, ST_AsText(shape) FROM gis_polygon;
id ST_AsText(shape)
1 POLYGON((-0.1681156881122417 47.54646568683867,-0.031445000320673 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.0318659991025925 47.310115814208984,-0.1681156881122417 47.54646568683867))
DROP TABLE gis_point, gis_line, gis_polygon;
73 changes: 73 additions & 0 deletions mysql-test/suite/innodb_gis/t/gis_precision.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# **************************************************
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a good idea to mention issue/bug number in description of the test case.
E.g. we can say:

PS-9121 : InnoDB updates the primary index but not the spatial index, crashing MySQL.

Test if MBR comparison used for InnoDB secondary index updates works well for values
which are close to each other.

# Test if MBR compairson used for InnoDB secondary
# index updates works well with more precise data
# **************************************************

--echo Create separate tables of supported geometric types
CREATE TABLE gis_point (
id INTEGER NOT NULL PRIMARY KEY,
shape POINT NOT NULL SRID 0,
SPATIAL KEY IND(shape)
) ENGINE=INNODB;

CREATE TABLE gis_line (
id INTEGER NOT NULL PRIMARY KEY,
shape LINESTRING NOT NULL SRID 0,
SPATIAL KEY IND(shape)
) ENGINE=INNODB;

CREATE TABLE gis_polygon(
id INTEGER NOT NULL PRIMARY KEY,
shape POLYGON NOT NULL SRID 0,
SPATIAL KEY IND(shape)
) ENGINE=INNODB;


--echo Point
INSERT INTO gis_point VALUES (1,POINT(0.0000000000000099,0));
SELECT id, ST_AsText(shape) FROM gis_point;

UPDATE gis_point SET shape = POINT(0.00000000000001, 0) WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_point;

DELETE FROM gis_point WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_point;

INSERT INTO gis_point VALUES (1,POINT(0.0000000000000099,0));
SELECT id, ST_AsText(shape) FROM gis_point;


--echo Line
INSERT INTO gis_line VALUES
(1, ST_LineFromText('LINESTRING(0.0000000000000099 0,1 0.0000000000000099)'));
SELECT id, ST_AsText(shape) FROM gis_line;

UPDATE gis_line SET shape = ST_LineFromText('LINESTRING(0.00000000000001 0,1 0.00000000000001)') WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_line;

DELETE FROM gis_line WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_line;

INSERT INTO gis_line VALUES (1, ST_LineFromText('LINESTRING(0.0000000000000099 0,1 0.0000000000000099)'));
SELECT id, ST_AsText(shape) FROM gis_line;


--echo Polygon
INSERT INTO gis_polygon VALUES
(1, ST_PolyFromText('POLYGON((-0.1681156881122417 47.54646568683867,-0.031445000320673 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.0318659991025925 47.310115814208984,-0.1681156881122417 47.54646568683867))'));
SELECT id, ST_AsText(shape) FROM gis_polygon;

UPDATE gis_polygon SET
shape = ST_PolyFromText('POLYGON((-0.168115688112241675 47.54646568683867,-0.03144500032067299 47.88496876305664,-0.849334763684143234 47.31022644042969,-0.03186599910259247 47.310115814208984,-0.168115688112241675 47.54646568683867))')
WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_polygon;

DELETE FROM gis_polygon WHERE id = 1;
SELECT id, ST_AsText(shape) FROM gis_polygon;

INSERT INTO gis_polygon VALUES
(1, ST_PolyFromText('POLYGON((-0.1681156881122417 47.54646568683867,-0.031445000320673 47.88496876305664,-0.8493347636841432 47.31022644042969,-0.0318659991025925 47.310115814208984,-0.1681156881122417 47.54646568683867))'));
SELECT id, ST_AsText(shape) FROM gis_polygon;


DROP TABLE gis_point, gis_line, gis_polygon;
15 changes: 15 additions & 0 deletions sql/gis/rtree_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,21 @@ bool mbr_contain_cmp(const dd::Spatial_reference_system *srs, rtr_mbr_t *a,
bool mbr_equal_cmp(const dd::Spatial_reference_system *srs, rtr_mbr_t *a,
rtr_mbr_t *b);

/// Checks if two MBRs are equal more precisely
///
/// For both MBRs, the coordinates of the MBR's minimum corners must be smaller
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it is worth to add asserts enforcing this similarly to those we have in mbr_equal_cmp() ?

/// than or equal to the corresponding coordinates of the maximum corner.
///
/// @param[in] a The first MBR.
/// @param[in] b The second MBR.
///
/// @retval true The two MBRs are equal.
/// @retval false The two MBRs aren't equal.
inline bool mbr_equal_precise_cmp(rtr_mbr_t *a, rtr_mbr_t *b) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ readability-identifier-length ⚠️
parameter name a is too short, expected at least 2 characters

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ readability-identifier-length ⚠️
parameter name b is too short, expected at least 2 characters

return a->xmin == b->xmin && a->xmax == b->xmax &&
a->ymin == b->ymin && a->ymax == b->ymax;
}

/// Checks if two MBRs intersect each other
///
/// @param[in] srs Spatial reference system.
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/row/row0sel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5679,7 +5679,7 @@ dberr_t row_search_mvcc(byte *buf, page_cur_mode_t mode,
UT_LOCATION_HERE, &heap);
rtr_get_mbr_from_rec(rec, index_offsets, &index_mbr);

if (mbr_equal_cmp(index->rtr_srs.get(), &clust_mbr, &index_mbr)) {
if (mbr_equal_precise_cmp(&clust_mbr, &index_mbr)) {
*is_dup_rec = true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/row/row0upd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,7 @@ bool row_upd_changes_ord_field_binary_func(dict_index_t *index,
mem_heap_free(temp_heap);
}

if (!mbr_equal_cmp(index->rtr_srs.get(), old_mbr, new_mbr)) {
if (!mbr_equal_precise_cmp(old_mbr, new_mbr)) {
return (true);
} else {
continue;
Expand Down
Loading