From: Date: May 10 2005 2:58am Subject: bk commit into 4.0 tree (sergefp:1.2099) BUG#10095 List-Archive: http://lists.mysql.com/internals/24758 X-Bug: 10095 Message-Id: <20050510005807.C8B05263053@pslp.mylan> Below is the list of changes that have just been committed into a local 4.0 repository of psergey. When psergey does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2099 05/05/10 02:58:05 sergefp@stripped +3 -0 Fix for BUG#10095: {wrong query results because of incorrect constant propagation} The problem: base_list::remove didn't modify base_list::last when removing the last list element. The fix: If we remove the last element, find the element before it (by walking from the beginning of the list) and set base_list::last accordingly. sql/sql_list.h 1.16 05/05/10 02:58:04 sergefp@stripped +67 -2 Fix for BUG#10095: {wrong query results because of incorrect constant propagation} The problem: base_list::remove didn't modify base_list::last when removing the last list element. The fix: If we remove the last element, find the element before it (by walking from the beginning of the list) and set base_list::last accordingly. mysql-test/t/select.test 1.27 05/05/10 02:58:04 sergefp@stripped +59 -0 Testcase for BUG#10095 mysql-test/r/select.result 1.37 05/05/10 02:58:03 sergefp@stripped +54 -0 Testcase for BUG#10095 # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: sergefp # Host: pslp.mylan # Root: /home/psergey/mysql-4.0-bug10095 --- 1.15/sql/sql_list.h 2004-03-04 17:16:10 +01:00 +++ 1.16/sql/sql_list.h 2005-05-10 02:58:04 +02:00 @@ -110,10 +110,27 @@ void remove(list_node **prev) { list_node *node=(*prev)->next; + if ((*prev)->next == *last) + { + /* + We're removing the last element from the list. Adjust "last" to + point to the previous element. + */ + list_node *cur= first; + if (cur == *prev) + { + last= &first; + } + else + { + while (cur->next != *prev) + cur= cur->next; + last= &(cur->next); + } + } delete *prev; *prev=node; - if (!--elements) - last= &first; + elements--; } inline void *pop(void) { @@ -129,6 +146,54 @@ inline bool is_empty() { return first == &end_of_list ; } inline list_node *last_ref() { return &end_of_list; } friend class base_list_iterator; + +#ifdef LIST_EXTRA_DEBUG + /* + Check list invariants and print results into trace. Invariants are: + - (*last) points to end_of_list + - There are no NULLs in the list. + - base_list::elements is the number of elements in the list. + + SYNOPSIS + list_invariants_ok() + name Name to print to trace file + + RETURN + 1 The list is Ok. + 0 List invariants are not met. + */ + + bool list_invariants_ok(const char *name) + { + base_list *list= this; + list_node *node= first; + uint cnt= 0; + + while (node->next != &end_of_list) + { + if (!node->info) + { + DBUG_PRINT("list_invariants",("%s: error: NULL element in the list", + name)); + return FALSE; + } + node= node->next; + cnt++; + } + if (last != &(node->next)) + { + DBUG_PRINT("list_invariants", ("%s: error: wrong last pointer", name)); + return FALSE; + } + if (cnt+1 != elements) + { + DBUG_PRINT("list_invariants", ("%s: error: wrong element count", name)); + return FALSE; + } + DBUG_PRINT("list_invariants", ("%s: list is ok", name)); + return TRUE; + } +#endif // LIST_EXTRA_DEBUG protected: void after(void *info,list_node *node) --- 1.36/mysql-test/r/select.result 2005-02-11 19:37:15 +01:00 +++ 1.37/mysql-test/r/select.result 2005-05-10 02:58:03 +02:00 @@ -2377,3 +2377,57 @@ t1 ALL NULL NULL NULL NULL 5 t2 ref a a 23 t1.a 5 DROP TABLE t1, t2; +CREATE TABLE t1 ( +kunde_intern_id int(10) unsigned NOT NULL default '0', +kunde_id int(10) unsigned NOT NULL default '0', +FK_firma_id int(10) unsigned NOT NULL default '0', +aktuell enum('Ja','Nein') NOT NULL default 'Ja', +vorname varchar(128) NOT NULL default '', +nachname varchar(128) NOT NULL default '', +geloescht enum('Ja','Nein') NOT NULL default 'Nein', +firma varchar(128) NOT NULL default '' +); +INSERT INTO t1 VALUES +(3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'), +(3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX'); +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1 +WHERE +( +( +( '' != '' AND firma LIKE CONCAT('%', '', '%')) +OR +(vorname LIKE CONCAT('%', 'Vorname1', '%') AND +nachname LIKE CONCAT('%', '1Nachname', '%') AND +'Vorname1' != '' AND 'xxxx' != '') +) +AND +( +aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 +) +) +; +kunde_id FK_firma_id aktuell vorname nachname geloescht +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, +geloescht FROM t1 +WHERE +( +( +aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 +) +AND +( +( '' != '' AND firma LIKE CONCAT('%', '', '%') ) +OR +( vorname LIKE CONCAT('%', 'Vorname1', '%') AND +nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND +'xxxx' != '') +) +) +; +kunde_id FK_firma_id aktuell vorname nachname geloescht +SELECT COUNT(*) FROM t1 WHERE +( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1)) +AND FK_firma_id = 2; +COUNT(*) +0 +drop table t1; --- 1.26/mysql-test/t/select.test 2005-02-11 07:14:41 +01:00 +++ 1.27/mysql-test/t/select.test 2005-05-10 02:58:04 +02:00 @@ -1924,3 +1924,62 @@ EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a; DROP TABLE t1, t2; + +# Test for BUG#10095 +CREATE TABLE t1 ( + kunde_intern_id int(10) unsigned NOT NULL default '0', + kunde_id int(10) unsigned NOT NULL default '0', + FK_firma_id int(10) unsigned NOT NULL default '0', + aktuell enum('Ja','Nein') NOT NULL default 'Ja', + vorname varchar(128) NOT NULL default '', + nachname varchar(128) NOT NULL default '', + geloescht enum('Ja','Nein') NOT NULL default 'Nein', + firma varchar(128) NOT NULL default '' +); + +INSERT INTO t1 VALUES + (3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'), + (3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX'); + + +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1 + WHERE + ( + ( + ( '' != '' AND firma LIKE CONCAT('%', '', '%')) + OR + (vorname LIKE CONCAT('%', 'Vorname1', '%') AND + nachname LIKE CONCAT('%', '1Nachname', '%') AND + 'Vorname1' != '' AND 'xxxx' != '') + ) + AND + ( + aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 + ) + ) + ; + +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, +geloescht FROM t1 + WHERE + ( + ( + aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 + ) + AND + ( + ( '' != '' AND firma LIKE CONCAT('%', '', '%') ) + OR + ( vorname LIKE CONCAT('%', 'Vorname1', '%') AND +nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND +'xxxx' != '') + ) + ) + ; + +SELECT COUNT(*) FROM t1 WHERE +( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1)) +AND FK_firma_id = 2; + +drop table t1; +