summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sanja@montyprogram.com>2012-09-05 23:23:58 +0300
committerunknown <sanja@montyprogram.com>2012-09-05 23:23:58 +0300
commit54bb28d4a151d0eb5c3b74edb40ddf6e118c124b (patch)
tree51f71f55c54b4fbf5bc0229527b40fc475d63211
parent589c62fefec759a467b6dec1badb2cd283564845 (diff)
downloadmariadb-git-54bb28d4a151d0eb5c3b74edb40ddf6e118c124b.tar.gz
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.
-rw-r--r--mysql-test/r/derived_view.result6
-rw-r--r--mysql-test/r/view.result33
-rw-r--r--mysql-test/t/view.test30
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item.h103
-rw-r--r--sql/table.cc22
-rw-r--r--sql/table.h1
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; }