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));
|
||||
ERROR HY000: Cannot cast 'point' as 'int' in assignment of `test`.`t1`.`b`
|
||||
# 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));
|
||||
|
||||
--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_ASSERT(fixed());
|
||||
SCOPE_EXIT([this] () {
|
||||
collector.reset();
|
||||
func.reset();
|
||||
res_receiver.reset();
|
||||
});
|
||||
|
||||
Geometry_ptr_with_buffer_and_mbr g1, g2;
|
||||
uint32 srid= 0;
|
||||
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))))
|
||||
{
|
||||
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);
|
||||
@ -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)))
|
||||
{
|
||||
str_value= 0;
|
||||
goto exit;
|
||||
DBUG_RETURN(str_value);
|
||||
}
|
||||
|
||||
collector.prepare_operation();
|
||||
if (func.alloc_states())
|
||||
goto exit;
|
||||
DBUG_RETURN(str_value);
|
||||
|
||||
operation.init(&func);
|
||||
|
||||
if (operation.count_all(&collector) ||
|
||||
operation.get_result(&res_receiver))
|
||||
goto exit;
|
||||
DBUG_RETURN(str_value);
|
||||
|
||||
|
||||
str_value->set_charset(&my_charset_bin);
|
||||
str_value->length(0);
|
||||
if (str_value->reserve(SRID_SIZE, 512))
|
||||
goto exit;
|
||||
DBUG_RETURN(str_value);
|
||||
str_value->q_append(srid);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
double res;
|
||||
|
@ -382,6 +382,8 @@ public:
|
||||
(expected_points > ((m_data_end - data) /
|
||||
(POINT_DATA_SIZE + extra_point_space))));
|
||||
}
|
||||
|
||||
bool operator==(Geometry &rhs) const;
|
||||
protected:
|
||||
const char *m_data;
|
||||
const char *m_data_end;
|
||||
|
Loading…
x
Reference in New Issue
Block a user