diff options
author | Alexander Barkov <bar@mariadb.org> | 2015-06-26 15:42:49 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2015-06-26 15:42:49 +0400 |
commit | 436411860ec54fda959910a3c88a1e393e1cee59 (patch) | |
tree | 25651900a88706de7693638b629d472d704aa1ff | |
parent | 4f828a1cac9a9c378a2a9f3c3ef0710eaf11ce02 (diff) | |
download | mariadb-git-436411860ec54fda959910a3c88a1e393e1cee59.tar.gz |
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
-rw-r--r-- | sql/item_create.cc | 2 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 146 | ||||
-rw-r--r-- | sql/item_geofunc.h | 22 | ||||
-rw-r--r-- | sql/spatial.h | 6 |
4 files changed, 106 insertions, 70 deletions
diff --git a/sql/item_create.cc b/sql/item_create.cc index a55c9ef3de4..0d2f794f76e 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -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); } diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index c4c01667d1b..710df57c5f4 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -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: diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index c4cf683fa9a..72dddee1fba 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -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 */ diff --git a/sql/spatial.h b/sql/spatial.h index b850d405228..6f50acac984 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -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 */ |