From 589c62fefec759a467b6dec1badb2cd283564845 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 31 Aug 2012 19:50:45 +0500 Subject: [PATCH 1/2] Bug #1043845 st_distance() results are incorrect depending on variable order. Autointersections of an object were treated as nodes, so the wrong result. per-file comments: mysql-test/r/gis.result Bug #1043845 st_distance() results are incorrect depending on variable order. test result updated. mysql-test/t/gis.test Bug #1043845 st_distance() results are incorrect depending on variable order. test case added. sql/item.cc small fix to make compilers happy. sql/item_geofunc.cc Bug #1043845 st_distance() results are incorrect depending on variable order. Skip intersection points when calculate distance. --- mysql-test/r/gis.result | 23 +++++++++++++++++++++++ mysql-test/t/gis.test | 16 ++++++++++++++++ sql/item.cc | 2 +- sql/item_geofunc.cc | 3 ++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index eab28b23550..f29d096fc57 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1473,3 +1473,26 @@ WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1; count(*) 1 DROP DATABASE gis_ogs; +# +# BUG #1043845 st_distance() results are incorrect depending on variable order +# +select st_distance(geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, + -95.9673057475387 36.1344478941074, + -95.9673063519371 36.134484524621, + -95.9673049102515 36.1343976584193)'), +geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)')) ; +st_distance(geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, + -95.9673057475387 36.1344478941074, + -95.9673063519371 36.134484524621, + +0.008148695928138 +select st_distance(geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)'), +geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, + -95.9673057475387 36.1344478941074, + -95.9673063519371 36.134484524621, + -95.9673049102515 36.1343976584193) ')) ; +st_distance(geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)'), +geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, + -95.9673057475387 36.1344478941074, + -95.9673063519371 36. +0.008148695928138 diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 95b1e63b828..cdbc253869e 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -1355,3 +1355,19 @@ WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1; #WHERE lakes.name = 'Blue Lake'; DROP DATABASE gis_ogs; + +--echo # +--echo # BUG #1043845 st_distance() results are incorrect depending on variable order +--echo # + +select st_distance(geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, + -95.9673057475387 36.1344478941074, + -95.9673063519371 36.134484524621, + -95.9673049102515 36.1343976584193)'), + geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)')) ; +select st_distance(geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)'), + geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, + -95.9673057475387 36.1344478941074, + -95.9673063519371 36.134484524621, + -95.9673049102515 36.1343976584193) ')) ; + diff --git a/sql/item.cc b/sql/item.cc index e125e57d2fc..bb6360f3f73 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8858,7 +8858,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) item->max_length, item->decimals)); fld_type= Field::field_type_merge(fld_type, get_real_type(item)); { - int item_decimals= item->decimals; + uint item_decimals= item->decimals; /* fix variable decimals which always is NOT_FIXED_DEC */ if (Field::result_merge_type(fld_type) == INT_RESULT) item_decimals= 0; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 172e0cbcd1f..522be28558f 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1693,7 +1693,8 @@ count_distance: for (dist_point= collector.get_first(); dist_point; dist_point= dist_point->get_next()) { /* We only check vertices of object 2 */ - if (dist_point->shape < obj2_si) + if (dist_point->type != Gcalc_heap::nt_shape_node || + dist_point->shape < obj2_si) continue; /* if we have an edge to check */ From 54bb28d4a151d0eb5c3b74edb40ddf6e118c124b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Sep 2012 23:23:58 +0300 Subject: [PATCH 2/2] MDEV-486 LP BUG#1010116 fix. Link view/derived table fields to a real table to check turning the table record to null row. Item_direct_view_ref wrapper now checks if table is turned to null row. --- mysql-test/r/derived_view.result | 6 +- mysql-test/r/view.result | 33 ++++++++++ mysql-test/t/view.test | 30 +++++++++ sql/item.cc | 1 + sql/item.h | 103 ++++++++++++++++++++++++++++--- sql/table.cc | 22 +++++++ sql/table.h | 1 + 7 files changed, 184 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index a4f7a71dcb5..6061fbb8800 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -1677,7 +1677,6 @@ SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b AND t.c = t1.a; b c a -8 c c EXPLAIN EXTENDED SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t @@ -1692,7 +1691,6 @@ SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b <> 0 AND t.c = t1.a; b c a -8 c c INSERT INTO t3 VALUES (100), (200); EXPLAIN EXTENDED SELECT t.b, t.c, t1.a @@ -1708,7 +1706,7 @@ SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b AND t.c = t1.a; b c a -8 c c +NULL NULL c EXPLAIN EXTENDED SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t @@ -1723,7 +1721,7 @@ SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b <> 0 AND t.c = t1.a; b c a -8 c c +NULL NULL c SET optimizer_switch=@save_optimizer_switch; DROP TABLE t1,t2,t3; # diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 56598583bb6..fc60d70317e 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4485,6 +4485,39 @@ a 1 drop view v2,v1; drop table t1; +# +# MDEV-486 LP BUG#1010116 Incorrect query results in +# view and derived tables +# +SELECT +`Derived1`.`id`, +`Derived2`.`Val1` +FROM (select 30631 as `id`) AS `Derived1` LEFT OUTER JOIN (SELECT +2 as `id`, +1 AS `Val1` +FROM (select 30631 as `id`) AS `Derived3`) AS `Derived2` ON `Derived1`.`id` = `Derived2`.`id`; +id Val1 +30631 NULL +create table t1 ( id int ); +insert into t1 values (30631); +create table t2 ( id int ); +insert into t2 values (30631); +create algorithm=MERGE view v2 as select 2 as id, 1 as val1 from t2; +select t1.*, v2.* from t1 left join v2 on t1.id = v2.id; +id id val1 +30631 NULL NULL +drop view v2; +drop table t1,t2; +create table t1 ( id int ); +insert into t1 values (30631); +create table t2 ( id int ); +insert into t2 values (30631); +create algorithm=MERGE view v2 as select 2 as id, id is null as bbb, id as iddqd, 1 as val1 from t2; +select t1.*, v2.* from t1 left join v2 on t1.id = v2.id; +id id bbb iddqd val1 +30631 NULL NULL NULL NULL +drop view v2; +drop table t1,t2; # ----------------------------------------------------------------- # -- End of 5.3 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6f11d6909ea..bd3b485034d 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4433,6 +4433,36 @@ select * from t1; drop view v2,v1; drop table t1; +--echo # +--echo # MDEV-486 LP BUG#1010116 Incorrect query results in +--echo # view and derived tables +--echo # + +SELECT +`Derived1`.`id`, +`Derived2`.`Val1` +FROM (select 30631 as `id`) AS `Derived1` LEFT OUTER JOIN (SELECT +2 as `id`, +1 AS `Val1` +FROM (select 30631 as `id`) AS `Derived3`) AS `Derived2` ON `Derived1`.`id` = `Derived2`.`id`; + +create table t1 ( id int ); +insert into t1 values (30631); +create table t2 ( id int ); +insert into t2 values (30631); +create algorithm=MERGE view v2 as select 2 as id, 1 as val1 from t2; +select t1.*, v2.* from t1 left join v2 on t1.id = v2.id; +drop view v2; +drop table t1,t2; + +create table t1 ( id int ); +insert into t1 values (30631); +create table t2 ( id int ); +insert into t2 values (30631); +create algorithm=MERGE view v2 as select 2 as id, id is null as bbb, id as iddqd, 1 as val1 from t2; +select t1.*, v2.* from t1 left join v2 on t1.id = v2.id; +drop view v2; +drop table t1,t2; --echo # ----------------------------------------------------------------- --echo # -- End of 5.3 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/item.cc b/sql/item.cc index bb6360f3f73..18a86aa2d1a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7339,6 +7339,7 @@ Item* Item_cache_wrapper::get_tmp_table_item(THD *thd_arg) bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) { + DBUG_ASSERT(1); /* view fild reference must be defined */ DBUG_ASSERT(*ref); /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ diff --git a/sql/item.h b/sql/item.h index 055225a79d7..5dde9cf9a3f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2925,20 +2925,29 @@ class Item_direct_view_ref :public Item_direct_ref { Item_equal *item_equal; TABLE_LIST *view; + TABLE *null_ref_table; + + bool check_null_ref() + { + if (null_ref_table == NULL) + { + null_ref_table= view->get_real_join_table(); + } + if (null_ref_table->null_row) + { + null_value= 1; + return TRUE; + } + return FALSE; + } public: Item_direct_view_ref(Name_resolution_context *context_arg, Item **item, const char *table_name_arg, const char *field_name_arg, TABLE_LIST *view_arg) :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg), - item_equal(0), view(view_arg) {} - /* Constructor need to process subselect with temporary tables (see Item) */ - Item_direct_view_ref(THD *thd, Item_direct_ref *item) - :Item_direct_ref(thd, item), item_equal(0) {} - Item_direct_view_ref(TABLE_LIST *view_arg, Item **item, - const char *field_name_arg) - :Item_direct_ref(view_arg, item, field_name_arg), item_equal(0) - {} + item_equal(0), view(view_arg), + null_ref_table(NULL) {} bool fix_fields(THD *, Item **); bool eq(const Item *item, bool binary_cmp) const; @@ -2969,6 +2978,84 @@ public: view_arg->view_used_tables|= (*ref)->used_tables(); return 0; } + void save_val(Field *to) + { + if (check_null_ref()) + to->set_null(); + else + Item_direct_ref::save_val(to); + } + double val_real() + { + if (check_null_ref()) + return 0; + else + return Item_direct_ref::val_real(); + } + longlong val_int() + { + if (check_null_ref()) + return 0; + else + return Item_direct_ref::val_int(); + } + String *val_str(String* tmp) + { + if (check_null_ref()) + return NULL; + else + return Item_direct_ref::val_str(tmp); + } + my_decimal *val_decimal(my_decimal *tmp) + { + if (check_null_ref()) + return NULL; + else + return Item_direct_ref::val_decimal(tmp); + } + bool val_bool() + { + if (check_null_ref()) + return 0; + else + return Item_direct_ref::val_bool(); + } + bool is_null() + { + if (check_null_ref()) + return 1; + else + return Item_direct_ref::is_null(); + } + bool get_date(MYSQL_TIME *ltime, uint fuzzydate) + { + if (check_null_ref()) + { + bzero((char*) ltime,sizeof(*ltime)); + return 1; + } + return Item_direct_ref::get_date(ltime, fuzzydate); + } + bool send(Protocol *protocol, String *buffer) + { + if (check_null_ref()) + return protocol->store_null(); + return Item_direct_ref::send(protocol, buffer); + } + void save_org_in_field(Field *field) + { + if (check_null_ref()) + field->set_null(); + else + Item_direct_ref::save_val(field); + } + void save_in_result_field(bool no_conversions) + { + if (check_null_ref()) + result_field->set_null(); + else + Item_direct_ref::save_in_result_field(no_conversions); + } }; diff --git a/sql/table.cc b/sql/table.cc index 2eb7eca6fb0..2be94c55205 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4441,6 +4441,28 @@ void TABLE_LIST::set_check_materialized() } } +TABLE *TABLE_LIST::get_real_join_table() +{ + TABLE_LIST *tbl= this; + while (tbl->table == NULL || tbl->table->reginfo.join_tab == NULL) + { + if (tbl->view == NULL && tbl->derived == NULL) + break; + /* we do not support merging of union yet */ + DBUG_ASSERT(tbl->view == NULL || + tbl->view->select_lex.next_select() == NULL); + DBUG_ASSERT(tbl->derived == NULL || + tbl->derived->first_select()->next_select() == NULL); + + if (tbl->table) + table= tbl->table; + tbl= (tbl->view != NULL ? + tbl->view->select_lex.get_table_list() : + tbl->derived->first_select()->get_table_list()); + } + return tbl->table; +} + Natural_join_column::Natural_join_column(Field_translator *field_param, TABLE_LIST *tab) diff --git a/sql/table.h b/sql/table.h index 6ce6c83c604..8ce73162aaf 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1671,6 +1671,7 @@ struct TABLE_LIST TABLE_LIST *find_underlying_table(TABLE *table); TABLE_LIST *first_leaf_for_name_resolution(); TABLE_LIST *last_leaf_for_name_resolution(); + TABLE *get_real_join_table(); bool is_leaf_for_name_resolution(); inline TABLE_LIST *top_table() { return belong_to_view ? belong_to_view : this; }