Moving ST_RELATE() implementation out of Item_func_precise_spatial_rel,
adding a separte class Item_func_spatial_relate for ST_RELATE(). This is a preparatory patch for: MDEV-8239 Reverse spatial operations OP(const, field) do not get optimized
This commit is contained in:
parent
4f828a1cac
commit
436411860e
@ -4427,7 +4427,7 @@ Create_func_relate Create_func_relate::s_singleton;
|
||||
Item*
|
||||
Create_func_relate::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *matrix)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_precise_rel(arg1, arg2, matrix);
|
||||
return new (thd->mem_root) Item_func_spatial_relate(arg1, arg2, matrix);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1018,8 +1018,6 @@ const char *Item_func_spatial_precise_rel::func_name() const
|
||||
return "st_crosses";
|
||||
case SP_OVERLAPS_FUNC:
|
||||
return "st_overlaps";
|
||||
case SP_RELATE_FUNC:
|
||||
return "st_relate";
|
||||
default:
|
||||
DBUG_ASSERT(0); // Should never happened
|
||||
return "sp_unknown";
|
||||
@ -1142,80 +1140,122 @@ static int setup_relate_func(Geometry *g1, Geometry *g2,
|
||||
|
||||
#define GIS_ZERO 0.00000000001
|
||||
|
||||
class Geometry_ptr_with_buffer_and_mbr
|
||||
{
|
||||
public:
|
||||
Geometry *geom;
|
||||
Geometry_buffer buffer;
|
||||
MBR mbr;
|
||||
bool construct(Item *item, String *tmp_value)
|
||||
{
|
||||
const char *c_end;
|
||||
String *res= item->val_str(tmp_value);
|
||||
return
|
||||
item->null_value ||
|
||||
!(geom= Geometry::construct(&buffer, res->ptr(), res->length())) ||
|
||||
geom->get_mbr(&mbr, &c_end) || !mbr.valid();
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{ return geom->store_shapes(trn); }
|
||||
};
|
||||
|
||||
|
||||
longlong Item_func_spatial_relate::val_int()
|
||||
{
|
||||
DBUG_ENTER("Item_func_spatial_relate::val_int");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
Geometry_ptr_with_buffer_and_mbr g1, g2;
|
||||
int result= 0;
|
||||
|
||||
if ((null_value= (g1.construct(args[0], &tmp_value1) ||
|
||||
g2.construct(args[1], &tmp_value2) ||
|
||||
func.reserve_op_buffer(1))))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
MBR umbr(g1.mbr, g2.mbr);
|
||||
collector.set_extent(umbr.xmin, umbr.xmax, umbr.ymin, umbr.ymax);
|
||||
g1.mbr.buffer(1e-5);
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
|
||||
String *matrix= args[2]->val_str(&tmp_matrix);
|
||||
if ((null_value= args[2]->null_value || matrix->length() != 9 ||
|
||||
setup_relate_func(g1.geom, g2.geom,
|
||||
&trn, &func, matrix->ptr())))
|
||||
goto exit;
|
||||
|
||||
collector.prepare_operation();
|
||||
scan_it.init(&collector);
|
||||
scan_it.killed= (int *) &(current_thd->killed);
|
||||
if (!func.alloc_states())
|
||||
result= func.check_function(scan_it);
|
||||
|
||||
exit:
|
||||
collector.reset();
|
||||
func.reset();
|
||||
scan_it.reset();
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_spatial_precise_rel::val_int()
|
||||
{
|
||||
DBUG_ENTER("Item_func_spatial_precise_rel::val_int");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String *res1;
|
||||
String *res2;
|
||||
String *res3;
|
||||
Geometry_buffer buffer1, buffer2;
|
||||
Geometry *g1, *g2;
|
||||
Geometry_ptr_with_buffer_and_mbr g1, g2;
|
||||
int result= 0;
|
||||
uint shape_a, shape_b;
|
||||
MBR umbr, mbr1, mbr2;
|
||||
const char *c_end;
|
||||
|
||||
res1= args[0]->val_str(&tmp_value1);
|
||||
res2= args[1]->val_str(&tmp_value2);
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
|
||||
if (func.reserve_op_buffer(1))
|
||||
if ((null_value= (g1.construct(args[0], &tmp_value1) ||
|
||||
g2.construct(args[1], &tmp_value2) ||
|
||||
func.reserve_op_buffer(1))))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if ((null_value=
|
||||
(args[0]->null_value || args[1]->null_value ||
|
||||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
|
||||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
|
||||
g1->get_mbr(&mbr1, &c_end) || !mbr1.valid() ||
|
||||
g2->get_mbr(&mbr2, &c_end) || !mbr2.valid())))
|
||||
goto exit;
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
|
||||
umbr= mbr1;
|
||||
umbr.add_mbr(&mbr2);
|
||||
MBR umbr(g1.mbr, g2.mbr);
|
||||
collector.set_extent(umbr.xmin, umbr.xmax, umbr.ymin, umbr.ymax);
|
||||
|
||||
mbr1.buffer(1e-5);
|
||||
g1.mbr.buffer(1e-5);
|
||||
|
||||
switch (spatial_rel) {
|
||||
case SP_CONTAINS_FUNC:
|
||||
if (!mbr1.contains(&mbr2))
|
||||
if (!g1.mbr.contains(&g2.mbr))
|
||||
goto exit;
|
||||
func.add_operation(Gcalc_function::v_find_f |
|
||||
Gcalc_function::op_not |
|
||||
Gcalc_function::op_difference, 2);
|
||||
/* Mind the g2 goes first. */
|
||||
null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn);
|
||||
null_value= g2.store_shapes(&trn) || g1.store_shapes(&trn);
|
||||
break;
|
||||
case SP_WITHIN_FUNC:
|
||||
mbr2.buffer(2e-5);
|
||||
if (!mbr1.within(&mbr2))
|
||||
g2.mbr.buffer(2e-5);
|
||||
if (!g1.mbr.within(&g2.mbr))
|
||||
goto exit;
|
||||
func.add_operation(Gcalc_function::v_find_f |
|
||||
Gcalc_function::op_not |
|
||||
Gcalc_function::op_difference, 2);
|
||||
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
||||
null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
|
||||
break;
|
||||
case SP_EQUALS_FUNC:
|
||||
if (!mbr1.contains(&mbr2))
|
||||
if (!g1.mbr.contains(&g2.mbr))
|
||||
goto exit;
|
||||
func.add_operation(Gcalc_function::v_find_f |
|
||||
Gcalc_function::op_not |
|
||||
Gcalc_function::op_symdifference, 2);
|
||||
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
||||
null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
|
||||
break;
|
||||
case SP_DISJOINT_FUNC:
|
||||
func.add_operation(Gcalc_function::v_find_f |
|
||||
Gcalc_function::op_not |
|
||||
Gcalc_function::op_intersection, 2);
|
||||
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
||||
null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
|
||||
break;
|
||||
case SP_INTERSECTS_FUNC:
|
||||
if (!mbr1.intersects(&mbr2))
|
||||
if (!g1.mbr.intersects(&g2.mbr))
|
||||
goto exit;
|
||||
func.add_operation(Gcalc_function::v_find_t |
|
||||
Gcalc_function::op_intersection, 2);
|
||||
null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
|
||||
null_value= g1.store_shapes(&trn) || g2.store_shapes(&trn);
|
||||
break;
|
||||
case SP_OVERLAPS_FUNC:
|
||||
case SP_CROSSES_FUNC:
|
||||
@ -1225,10 +1265,10 @@ longlong Item_func_spatial_precise_rel::val_int()
|
||||
func.add_operation(Gcalc_function::v_find_t |
|
||||
Gcalc_function::op_intersection, 2);
|
||||
shape_a= func.get_next_expression_pos();
|
||||
if ((null_value= g1->store_shapes(&trn)))
|
||||
if ((null_value= g1.store_shapes(&trn)))
|
||||
break;
|
||||
shape_b= func.get_next_expression_pos();
|
||||
if ((null_value= g2->store_shapes(&trn)))
|
||||
if ((null_value= g2.store_shapes(&trn)))
|
||||
break;
|
||||
if (func.reserve_op_buffer(7))
|
||||
break;
|
||||
@ -1251,24 +1291,17 @@ longlong Item_func_spatial_precise_rel::val_int()
|
||||
Gcalc_function::op_intersection, 2);
|
||||
func.add_operation(Gcalc_function::op_internals, 1);
|
||||
shape_a= func.get_next_expression_pos();
|
||||
if ((null_value= g1->store_shapes(&trn)))
|
||||
if ((null_value= g1.store_shapes(&trn)))
|
||||
break;
|
||||
func.add_operation(Gcalc_function::op_internals, 1);
|
||||
shape_b= func.get_next_expression_pos();
|
||||
if ((null_value= g2->store_shapes(&trn)))
|
||||
if ((null_value= g2.store_shapes(&trn)))
|
||||
break;
|
||||
func.add_operation(Gcalc_function::v_find_t |
|
||||
Gcalc_function::op_intersection, 2);
|
||||
func.repeat_expression(shape_a);
|
||||
func.repeat_expression(shape_b);
|
||||
break;
|
||||
case SP_RELATE_FUNC:
|
||||
res3= args[2]->val_str(&tmp_matrix);
|
||||
if ((null_value= args[2]->null_value))
|
||||
break;
|
||||
null_value= (res3->length() != 9) ||
|
||||
setup_relate_func(g1, g2, &trn, &func, res3->ptr());
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(FALSE);
|
||||
break;
|
||||
@ -1303,34 +1336,25 @@ String *Item_func_spatial_operation::val_str(String *str_value)
|
||||
{
|
||||
DBUG_ENTER("Item_func_spatial_operation::val_str");
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
String *res1= args[0]->val_str(&tmp_value1);
|
||||
String *res2= args[1]->val_str(&tmp_value2);
|
||||
Geometry_buffer buffer1, buffer2;
|
||||
Geometry *g1, *g2;
|
||||
Geometry_ptr_with_buffer_and_mbr g1, g2;
|
||||
uint32 srid= 0;
|
||||
Gcalc_operation_transporter trn(&func, &collector);
|
||||
MBR mbr1, mbr2;
|
||||
const char *c_end;
|
||||
|
||||
if (func.reserve_op_buffer(1))
|
||||
DBUG_RETURN(0);
|
||||
func.add_operation(spatial_op, 2);
|
||||
|
||||
if ((null_value=
|
||||
(args[0]->null_value || args[1]->null_value ||
|
||||
!(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
|
||||
!(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
|
||||
g1->get_mbr(&mbr1, &c_end) || !mbr1.valid() ||
|
||||
g2->get_mbr(&mbr2, &c_end) || !mbr2.valid())))
|
||||
if ((null_value= (g1.construct(args[0], &tmp_value1) ||
|
||||
g2.construct(args[1], &tmp_value2))))
|
||||
{
|
||||
str_value= 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbr1.add_mbr(&mbr2);
|
||||
collector.set_extent(mbr1.xmin, mbr1.xmax, mbr1.ymin, mbr1.ymax);
|
||||
g1.mbr.add_mbr(&g2.mbr);
|
||||
collector.set_extent(g1.mbr.xmin, g1.mbr.xmax, g1.mbr.ymin, g1.mbr.ymax);
|
||||
|
||||
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;
|
||||
goto exit;
|
||||
@ -1353,7 +1377,7 @@ String *Item_func_spatial_operation::val_str(String *str_value)
|
||||
str_value->length(0);
|
||||
str_value->q_append(srid);
|
||||
|
||||
if (!Geometry::create_from_opresult(&buffer1, str_value, res_receiver))
|
||||
if (!Geometry::create_from_opresult(&g1.buffer, str_value, res_receiver))
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
|
@ -281,9 +281,6 @@ public:
|
||||
Item_func_spatial_rel(Item *a, Item *b, enum Functype sp_rel)
|
||||
:Item_bool_func(a, b), spatial_rel(sp_rel)
|
||||
{ }
|
||||
Item_func_spatial_rel(Item *a, Item *b, Item *c, enum Functype sp_rel)
|
||||
:Item_bool_func(a, b, c), spatial_rel(sp_rel)
|
||||
{ }
|
||||
enum Functype functype() const { return spatial_rel; }
|
||||
enum Functype rev_functype() const { return spatial_rel; }
|
||||
bool is_null() { (void) val_int(); return null_value; }
|
||||
@ -314,19 +311,30 @@ class Item_func_spatial_precise_rel: public Item_func_spatial_rel
|
||||
Gcalc_heap collector;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
Gcalc_function func;
|
||||
String tmp_matrix;
|
||||
public:
|
||||
Item_func_spatial_precise_rel(Item *a, Item *b, enum Functype sp_rel)
|
||||
:Item_func_spatial_rel(a, b, sp_rel), collector()
|
||||
{ }
|
||||
Item_func_spatial_precise_rel(Item *a, Item *b, Item *matrix)
|
||||
:Item_func_spatial_rel(a, b, matrix, SP_RELATE_FUNC)
|
||||
{ }
|
||||
longlong val_int();
|
||||
const char *func_name() const;
|
||||
};
|
||||
|
||||
|
||||
class Item_func_spatial_relate: public Item_bool_func
|
||||
{
|
||||
Gcalc_heap collector;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
Gcalc_function func;
|
||||
String tmp_value1, tmp_value2, tmp_matrix;
|
||||
public:
|
||||
Item_func_spatial_relate(Item *a, Item *b, Item *matrix)
|
||||
:Item_bool_func(a, b, matrix)
|
||||
{ }
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "st_relate"; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Spatial operations
|
||||
*/
|
||||
|
@ -71,7 +71,11 @@ struct MBR
|
||||
MBR(const st_point_2d &min, const st_point_2d &max)
|
||||
:xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
|
||||
{}
|
||||
|
||||
|
||||
MBR(const MBR &mbr1, const MBR &mbr2)
|
||||
:xmin(mbr1.xmin), ymin(mbr1.ymin), xmax(mbr1.xmax), ymax(mbr1.ymax)
|
||||
{ add_mbr(&mbr2); }
|
||||
|
||||
inline void add_xy(double x, double y)
|
||||
{
|
||||
/* Not using "else" for proper one point MBR calculation */
|
||||
|
Loading…
x
Reference in New Issue
Block a user