diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2015-06-22 23:33:35 +0500 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2015-06-22 23:33:35 +0500 |
commit | fb3e31203f74ec95c99e9ec4123debf67d8815e4 (patch) | |
tree | a56d6726febc35bd777f86f970daa3775a71e193 /sql/gcalc_tools.cc | |
parent | 0357791e3c291c47fe128954dac45c271f721b2a (diff) | |
download | mariadb-git-fb3e31203f74ec95c99e9ec4123debf67d8815e4.tar.gz |
MDEV-7925 Inconsistent behavior of ST_Touches with a POINT as one of arguments.
Some cases of the feature's borders were treated incorrectly.
Diffstat (limited to 'sql/gcalc_tools.cc')
-rw-r--r-- | sql/gcalc_tools.cc | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 2d770fd45d6..5aac8a71249 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -143,6 +143,9 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, { if (set_type == 0) result= i_states[n_shape] | b_states[n_shape]; + /* the last call for the count_internal outside of all shapes. */ + else if (set_type == 1) + result= 0; else if (set_type == op_border) result= b_states[n_shape]; else if (set_type == op_internals) @@ -158,7 +161,8 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, if (next_func == op_border || next_func == op_internals) { - result= count_internal(cur_func, next_func, &cur_func); + result= count_internal(cur_func, + (set_type == 1) ? set_type : next_func, &cur_func); goto exit; } @@ -180,16 +184,34 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, switch (next_func) { case op_union: - result= result | next_res; + if (result == result_true || next_res == result_true) + result= result_true; + else if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result_false; break; case op_intersection: - result= result & next_res; + if (result == result_false || next_res == result_false) + result= result_false; + else if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result_true; break; case op_symdifference: - result= result ^ next_res; + if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result ^ next_res; break; case op_difference: - result= result & !next_res; + if (result == result_false || next_res == result_true) + result= result_false; + else if (result == result_unknown || next_res == result_unknown) + result= result_unknown; + else + result= result_true; break; default: GCALC_DBUG_ASSERT(FALSE); @@ -197,24 +219,35 @@ int Gcalc_function::count_internal(const char *cur_func, uint set_type, } exit: - result^= mask; + if (result != result_unknown) + result^= mask; if (v_state != v_empty) { switch (v_state) { case v_find_t: - if (result) + if (result == result_true) { c_op= (c_op & ~v_mask) | v_t_found; int4store(sav_cur_func, c_op); - }; + } + else + { + if (set_type != 1) + result= result_unknown; + } break; case v_find_f: - if (!result) + if (result == result_false) { c_op= (c_op & ~v_mask) | v_f_found; int4store(sav_cur_func, c_op); - }; + } + else + { + if (set_type != 1) + result= result_unknown; + } break; case v_t_found: result= 1; @@ -264,6 +297,7 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) { const Gcalc_scan_iterator::point *eq_start, *cur_eq; const Gcalc_scan_iterator::event_point *events; + int result; GCALC_DBUG_ENTER("Gcalc_function::check_function"); while (scan_it.more_points()) @@ -288,8 +322,8 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) if (events->event == scev_end) set_b_state(events->get_shape()); - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); clear_b_states(); continue; } @@ -307,8 +341,8 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) set_i_state(si); } - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); /* Set back states changed in the loop above. */ for (events= scan_it.get_events(); events; events= events->get_next()) @@ -316,10 +350,10 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) gcalc_shape_info si= events->get_shape(); if (events->event == scev_thread || events->event == scev_end || - events->event == scev_single_point || - (get_shape_kind(si) == Gcalc_function::shape_polygon)) + get_shape_kind(si) == Gcalc_function::shape_polygon) clear_b_state(si); - else if (get_shape_kind(si) == Gcalc_function::shape_line) + else if (events->event == scev_single_point || + get_shape_kind(si) == Gcalc_function::shape_line) clear_i_state(si); } @@ -343,8 +377,8 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) else invert_i_state(si); } - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next()) { @@ -357,12 +391,13 @@ int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it) else invert_i_state(cur_eq->get_shape()); } - if (count()) - GCALC_DBUG_RETURN(1); + if ((result= count()) != result_unknown) + GCALC_DBUG_RETURN(result); + eq_start= pit.point(); } while (pit.point() != scan_it.get_event_end()); } - GCALC_DBUG_RETURN(0); + GCALC_DBUG_RETURN(count_last()); } |