Loading mysql-test/r/group_by.result +6 −0 Original line number Diff line number Diff line Loading @@ -96,3 +96,9 @@ xID xID1 Level 2 2 ** 3 134 *** 4 185 **** pid c1id c2id value id active id active 1 1 NULL 1 1 Yes NULL NULL 1 NULL 3 3 NULL NULL 3 Yes 1 4 NULL 4 4 Yes NULL NULL max(value) 4 mysql-test/t/group_by.test +40 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ # Test of group (Failed for Lars Hoss <lh@pbm.de>) # drop table if exists t1,t2; drop table if exists t1,t2,t3; CREATE TABLE t1 ( spID int(10) unsigned, userID int(10) unsigned, Loading Loading @@ -273,3 +273,42 @@ insert into t1 values (1,244,NULL),(2,243,NULL),(134,223,NULL),(185,186,NULL); select S.ID as xID, S.ID1 as xID1 from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2; select S.ID as xID, S.ID1 as xID1, repeat('*',count(distinct yS.ID)) as Level from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2 group by xID order by xID1; drop table t1; # # Problem with MAX and LEFT JOIN # CREATE TABLE t1 ( pid int(11) unsigned NOT NULL default '0', c1id int(11) unsigned default NULL, c2id int(11) unsigned default NULL, value int(11) unsigned NOT NULL default '0', UNIQUE KEY pid2 (pid,c1id,c2id), UNIQUE KEY pid (pid,value) ) TYPE=MyISAM; INSERT INTO t1 VALUES (1, 1, NULL, 1),(1, 2, NULL, 2),(1, NULL, 3, 3),(1, 4, NULL, 4),(1, 5, NULL, 5); CREATE TABLE t2 ( id int(11) unsigned NOT NULL default '0', active enum('Yes','No') NOT NULL default 'Yes', PRIMARY KEY (id) ) TYPE=MyISAM; INSERT INTO t2 VALUES (1, 'Yes'),(2, 'No'),(4, 'Yes'),(5, 'No'); CREATE TABLE t3 ( id int(11) unsigned NOT NULL default '0', active enum('Yes','No') NOT NULL default 'Yes', PRIMARY KEY (id) ); INSERT INTO t3 VALUES (3, 'Yes'); select * from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); select max(value) from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); drop table t1,t2,t3; sql/item_cmpfunc.cc +39 −0 Original line number Diff line number Diff line Loading @@ -1219,6 +1219,45 @@ longlong Item_cond_or::val_int() return 0; } /* Create an AND expression from two expressions SYNOPSIS and_expressions() a expression or NULL b expression. org_item Don't modify a if a == *org_item If a == NULL, org_item is set to point at b, to ensure that future calls will not modify b. NOTES This will not modify item pointed to by org_item or b The idea is that one can call this in a loop and create and 'and' over all items without modifying any of the original items. RETURN NULL Error Item */ Item *and_expressions(Item *a, Item *b, Item **org_item) { if (!a) return (*org_item= (Item*) b); if (a == *org_item) { Item_cond *res; if ((res= new Item_cond_and(a, (Item*) b))) res->used_tables_cache= a->used_tables() | b->used_tables(); return res; } if (((Item_cond_and*) a)->add((Item*) b)) return 0; ((Item_cond_and*) a)->used_tables_cache|= b->used_tables(); return a; } longlong Item_func_isnull::val_int() { /* Loading sql/item_cmpfunc.h +2 −0 Original line number Diff line number Diff line Loading @@ -576,3 +576,5 @@ inline Item *and_conds(Item *a,Item *b) cond->update_used_tables(); return cond; } Item *and_expressions(Item *a, Item *b, Item **org_item); sql/opt_sum.cc +13 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) bool recalc_const_item=0; table_map removed_tables=0; Item *item; COND *org_conds= conds; /* Add all ON conditions to WHERE condition */ for (TABLE_LIST *tl=tables; tl ; tl= tl->next) { if (tl->on_expr) conds= and_expressions(conds, tl->on_expr, &org_conds); } /* Iterate through item is select part and replace COUNT(), MIN() and MAX() with constants (if possible) */ while ((item= it++)) { Loading Loading
mysql-test/r/group_by.result +6 −0 Original line number Diff line number Diff line Loading @@ -96,3 +96,9 @@ xID xID1 Level 2 2 ** 3 134 *** 4 185 **** pid c1id c2id value id active id active 1 1 NULL 1 1 Yes NULL NULL 1 NULL 3 3 NULL NULL 3 Yes 1 4 NULL 4 4 Yes NULL NULL max(value) 4
mysql-test/t/group_by.test +40 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ # Test of group (Failed for Lars Hoss <lh@pbm.de>) # drop table if exists t1,t2; drop table if exists t1,t2,t3; CREATE TABLE t1 ( spID int(10) unsigned, userID int(10) unsigned, Loading Loading @@ -273,3 +273,42 @@ insert into t1 values (1,244,NULL),(2,243,NULL),(134,223,NULL),(185,186,NULL); select S.ID as xID, S.ID1 as xID1 from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2; select S.ID as xID, S.ID1 as xID1, repeat('*',count(distinct yS.ID)) as Level from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2 group by xID order by xID1; drop table t1; # # Problem with MAX and LEFT JOIN # CREATE TABLE t1 ( pid int(11) unsigned NOT NULL default '0', c1id int(11) unsigned default NULL, c2id int(11) unsigned default NULL, value int(11) unsigned NOT NULL default '0', UNIQUE KEY pid2 (pid,c1id,c2id), UNIQUE KEY pid (pid,value) ) TYPE=MyISAM; INSERT INTO t1 VALUES (1, 1, NULL, 1),(1, 2, NULL, 2),(1, NULL, 3, 3),(1, 4, NULL, 4),(1, 5, NULL, 5); CREATE TABLE t2 ( id int(11) unsigned NOT NULL default '0', active enum('Yes','No') NOT NULL default 'Yes', PRIMARY KEY (id) ) TYPE=MyISAM; INSERT INTO t2 VALUES (1, 'Yes'),(2, 'No'),(4, 'Yes'),(5, 'No'); CREATE TABLE t3 ( id int(11) unsigned NOT NULL default '0', active enum('Yes','No') NOT NULL default 'Yes', PRIMARY KEY (id) ); INSERT INTO t3 VALUES (3, 'Yes'); select * from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); select max(value) from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); drop table t1,t2,t3;
sql/item_cmpfunc.cc +39 −0 Original line number Diff line number Diff line Loading @@ -1219,6 +1219,45 @@ longlong Item_cond_or::val_int() return 0; } /* Create an AND expression from two expressions SYNOPSIS and_expressions() a expression or NULL b expression. org_item Don't modify a if a == *org_item If a == NULL, org_item is set to point at b, to ensure that future calls will not modify b. NOTES This will not modify item pointed to by org_item or b The idea is that one can call this in a loop and create and 'and' over all items without modifying any of the original items. RETURN NULL Error Item */ Item *and_expressions(Item *a, Item *b, Item **org_item) { if (!a) return (*org_item= (Item*) b); if (a == *org_item) { Item_cond *res; if ((res= new Item_cond_and(a, (Item*) b))) res->used_tables_cache= a->used_tables() | b->used_tables(); return res; } if (((Item_cond_and*) a)->add((Item*) b)) return 0; ((Item_cond_and*) a)->used_tables_cache|= b->used_tables(); return a; } longlong Item_func_isnull::val_int() { /* Loading
sql/item_cmpfunc.h +2 −0 Original line number Diff line number Diff line Loading @@ -576,3 +576,5 @@ inline Item *and_conds(Item *a,Item *b) cond->update_used_tables(); return cond; } Item *and_expressions(Item *a, Item *b, Item **org_item);
sql/opt_sum.cc +13 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) bool recalc_const_item=0; table_map removed_tables=0; Item *item; COND *org_conds= conds; /* Add all ON conditions to WHERE condition */ for (TABLE_LIST *tl=tables; tl ; tl= tl->next) { if (tl->on_expr) conds= and_expressions(conds, tl->on_expr, &org_conds); } /* Iterate through item is select part and replace COUNT(), MIN() and MAX() with constants (if possible) */ while ((item= it++)) { Loading