summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorigor@rurik.mysql.com <>2005-07-16 18:28:09 -0700
committerigor@rurik.mysql.com <>2005-07-16 18:28:09 -0700
commit553f2a59f37e0e12f245134f95ea5d93a342b77e (patch)
tree5adb79b583d6818c30f26a1c7d4f8adaffce4367 /sql/sql_select.cc
parent36945e144c73d2da0c03c108603aecedf24b4608 (diff)
parentff0c7f22cfab033022d4090c7cb324d4b4ace619 (diff)
downloadmariadb-git-553f2a59f37e0e12f245134f95ea5d93a342b77e.tar.gz
Merge ibabaev@bk-internal.mysql.com:/home/bk/mysql-4.1
into rurik.mysql.com:/home/igor/mysql-4.1
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc37
1 files changed, 33 insertions, 4 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7abdde25911..a70fa1c8d5e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3508,7 +3508,23 @@ inline void add_cond_and_fix(Item **e1, Item *e2)
(where othertbl is a non-const table and othertbl.field may be NULL)
and add them to conditions on correspoding tables (othertbl in this
example).
-
+
+ Exception from that is the case when referred_tab->join != join.
+ I.e. don't add NOT NULL constraints from any embedded subquery.
+ Consider this query:
+ SELECT A.f2 FROM t1 LEFT JOIN t2 A ON A.f2 = f1
+ WHERE A.f3=(SELECT MIN(f3) FROM t2 C WHERE A.f4 = C.f4) OR A.f3 IS NULL;
+ Here condition A.f3 IS NOT NULL is going to be added to the WHERE
+ condition of the embedding query.
+ Another example:
+ SELECT * FROM t10, t11 WHERE (t10.a < 10 OR t10.a IS NULL)
+ AND t11.b <=> t10.b AND (t11.a = (SELECT MAX(a) FROM t12
+ WHERE t12.b = t10.a ));
+ Here condition t10.a IS NOT NULL is going to be added.
+ In both cases addition of NOT NULL condition will erroneously reject
+ some rows of the result set.
+ referred_tab->join != join constraint would disallow such additions.
+
This optimization doesn't affect the choices that ref, range, or join
optimizer make. This was intentional because this was added after 4.1
was GA.
@@ -3539,11 +3555,24 @@ static void add_not_null_conds(JOIN *join)
DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
Item_field *not_null_item= (Item_field*)item;
JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab;
- Item_func_isnotnull *notnull;
+ /*
+ For UPDATE queries such as:
+ UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1);
+ not_null_item is the t1.f1, but it's referred_tab is 0.
+ */
+ if (!referred_tab || referred_tab->join != join)
+ continue;
+ Item *notnull;
if (!(notnull= new Item_func_isnotnull(not_null_item)))
DBUG_VOID_RETURN;
-
- notnull->quick_fix_field();
+ /*
+ We need to do full fix_fields() call here in order to have correct
+ notnull->const_item(). This is needed e.g. by test_quick_select
+ when it is called from make_join_select after this function is
+ called.
+ */
+ if (notnull->fix_fields(join->thd, join->tables_list, &notnull))
+ DBUG_VOID_RETURN;
DBUG_EXECUTE("where",print_where(notnull,
referred_tab->table->table_name););
add_cond_and_fix(&referred_tab->select_cond, notnull);