MDEV-35739 ST_INTERSECTION precise self-intersection
ST_INTERSECTION(geom_1, geom_1) returns geom_1 exactly. Replaces 'goto exit;' in Item_func_spatial_operation::val_str with SCOPE_EXIT. This was done to leverage existing geometry construction calls without incurring compiler errors caused by skipping initialization on goto.
This commit is contained in:
parent
67e6fdee05
commit
06866a5e12
@ -5569,3 +5569,24 @@ ERROR HY000: Cannot cast 'int' as 'point' in assignment of `test`.`t1`.`b`
|
|||||||
CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a));
|
CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a));
|
||||||
ERROR HY000: Cannot cast 'point' as 'int' in assignment of `test`.`t1`.`b`
|
ERROR HY000: Cannot cast 'point' as 'int' in assignment of `test`.`t1`.`b`
|
||||||
# End of 11.5 tests
|
# End of 11.5 tests
|
||||||
|
#
|
||||||
|
# Start of 11.8 tests
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# MDEV-35739 Linestring self-intersection equality
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(geom geometry NOT NULL);
|
||||||
|
INSERT INTO t1 (geom) VALUES(ST_GeomFromText('LINESTRING(2 2,4 4,6 2,3 2,2 4)'));
|
||||||
|
SELECT ST_ASTEXT(geom) FROM t1;
|
||||||
|
ST_ASTEXT(geom)
|
||||||
|
LINESTRING(2 2,4 4,6 2,3 2,2 4)
|
||||||
|
SELECT ST_EQUALS(geom, ST_INTERSECTION(geom, geom)) AS isequal, ST_ASTEXT(ST_INTERSECTION(geom, geom)) AS intersection FROM t1;
|
||||||
|
isequal intersection
|
||||||
|
1 LINESTRING(2 2,4 4,6 2,3 2,2 4)
|
||||||
|
SELECT ST_AsText(ST_SYMDIFFERENCE(geom, ST_Intersection(geom, geom))) FROM t1;
|
||||||
|
ST_AsText(ST_SYMDIFFERENCE(geom, ST_Intersection(geom, geom)))
|
||||||
|
GEOMETRYCOLLECTION EMPTY
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# End of 11.8 tests
|
||||||
|
#
|
||||||
|
@ -3574,3 +3574,21 @@ CREATE TABLE t1 (a INT, b POINT GENERATED ALWAYS AS (a));
|
|||||||
CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a));
|
CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a));
|
||||||
|
|
||||||
--echo # End of 11.5 tests
|
--echo # End of 11.5 tests
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Start of 11.8 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-35739 Linestring self-intersection equality
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1(geom geometry NOT NULL);
|
||||||
|
INSERT INTO t1 (geom) VALUES(ST_GeomFromText('LINESTRING(2 2,4 4,6 2,3 2,2 4)'));
|
||||||
|
SELECT ST_ASTEXT(geom) FROM t1;
|
||||||
|
SELECT ST_EQUALS(geom, ST_INTERSECTION(geom, geom)) AS isequal, ST_ASTEXT(ST_INTERSECTION(geom, geom)) AS intersection FROM t1;
|
||||||
|
SELECT ST_AsText(ST_SYMDIFFERENCE(geom, ST_Intersection(geom, geom))) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 11.8 tests
|
||||||
|
--echo #
|
||||||
|
@ -1542,6 +1542,12 @@ String *Item_func_spatial_operation::val_str(String *str_value)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_spatial_operation::val_str");
|
DBUG_ENTER("Item_func_spatial_operation::val_str");
|
||||||
DBUG_ASSERT(fixed());
|
DBUG_ASSERT(fixed());
|
||||||
|
SCOPE_EXIT([this] () {
|
||||||
|
collector.reset();
|
||||||
|
func.reset();
|
||||||
|
res_receiver.reset();
|
||||||
|
});
|
||||||
|
|
||||||
Geometry_ptr_with_buffer_and_mbr g1, g2;
|
Geometry_ptr_with_buffer_and_mbr g1, g2;
|
||||||
uint32 srid= 0;
|
uint32 srid= 0;
|
||||||
Gcalc_operation_transporter trn(&func, &collector);
|
Gcalc_operation_transporter trn(&func, &collector);
|
||||||
@ -1554,7 +1560,23 @@ String *Item_func_spatial_operation::val_str(String *str_value)
|
|||||||
g2.construct(args[1], &tmp_value2))))
|
g2.construct(args[1], &tmp_value2))))
|
||||||
{
|
{
|
||||||
str_value= 0;
|
str_value= 0;
|
||||||
goto exit;
|
DBUG_RETURN(str_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Optimization to evaluate the particular self-intersection
|
||||||
|
ST_INTERSECTION(geom, geom);
|
||||||
|
*/
|
||||||
|
if (spatial_op == Gcalc_function::op_type::op_intersection &&
|
||||||
|
*g1.geom == *g2.geom)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Return either argument as the result, it doesn't matter which because
|
||||||
|
they're identical.
|
||||||
|
*/
|
||||||
|
String *sres= args[0]->val_str(&tmp_value1); // tmp_value1 is empty...
|
||||||
|
str_value->swap(*sres); // ...so swap the val_str result with str_value...
|
||||||
|
DBUG_RETURN(str_value); // ...to create a valid query result.
|
||||||
}
|
}
|
||||||
|
|
||||||
g1.mbr.add_mbr(&g2.mbr);
|
g1.mbr.add_mbr(&g2.mbr);
|
||||||
@ -1563,33 +1585,29 @@ String *Item_func_spatial_operation::val_str(String *str_value)
|
|||||||
if ((null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn)))
|
if ((null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn)))
|
||||||
{
|
{
|
||||||
str_value= 0;
|
str_value= 0;
|
||||||
goto exit;
|
DBUG_RETURN(str_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
collector.prepare_operation();
|
collector.prepare_operation();
|
||||||
if (func.alloc_states())
|
if (func.alloc_states())
|
||||||
goto exit;
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
operation.init(&func);
|
operation.init(&func);
|
||||||
|
|
||||||
if (operation.count_all(&collector) ||
|
if (operation.count_all(&collector) ||
|
||||||
operation.get_result(&res_receiver))
|
operation.get_result(&res_receiver))
|
||||||
goto exit;
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
|
|
||||||
str_value->set_charset(&my_charset_bin);
|
str_value->set_charset(&my_charset_bin);
|
||||||
str_value->length(0);
|
str_value->length(0);
|
||||||
if (str_value->reserve(SRID_SIZE, 512))
|
if (str_value->reserve(SRID_SIZE, 512))
|
||||||
goto exit;
|
DBUG_RETURN(str_value);
|
||||||
str_value->q_append(srid);
|
str_value->q_append(srid);
|
||||||
|
|
||||||
if (!Geometry::create_from_opresult(&g1.buffer, str_value, res_receiver))
|
if (!Geometry::create_from_opresult(&g1.buffer, str_value, res_receiver))
|
||||||
goto exit;
|
DBUG_RETURN(str_value);
|
||||||
|
|
||||||
exit:
|
|
||||||
collector.reset();
|
|
||||||
func.reset();
|
|
||||||
res_receiver.reset();
|
|
||||||
DBUG_RETURN(str_value);
|
DBUG_RETURN(str_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,6 +422,28 @@ int Geometry::bbox_as_json(String *wkt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geometry::operator==
|
||||||
|
*
|
||||||
|
* @param rhs a Geometry instance to compare to *this
|
||||||
|
* @return true when *this is the same Geometry as rhs, false otherwise. If
|
||||||
|
* either *this or rhs have no Geometry associated (because, for
|
||||||
|
* example, they are built with the default constructor) then the
|
||||||
|
* comparison will always be false.
|
||||||
|
*/
|
||||||
|
bool Geometry::operator==(Geometry &rhs) const
|
||||||
|
{
|
||||||
|
if (!m_data || !rhs.m_data)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const ptrdiff_t len= m_data_end - m_data;
|
||||||
|
if (len != rhs.m_data_end - rhs.m_data)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return memcmp(m_data, rhs.m_data, len) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo)
|
static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo)
|
||||||
{
|
{
|
||||||
double res;
|
double res;
|
||||||
|
@ -382,6 +382,8 @@ public:
|
|||||||
(expected_points > ((m_data_end - data) /
|
(expected_points > ((m_data_end - data) /
|
||||||
(POINT_DATA_SIZE + extra_point_space))));
|
(POINT_DATA_SIZE + extra_point_space))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(Geometry &rhs) const;
|
||||||
protected:
|
protected:
|
||||||
const char *m_data;
|
const char *m_data;
|
||||||
const char *m_data_end;
|
const char *m_data_end;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user