summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/select.result54
-rw-r--r--mysql-test/t/select.test59
-rw-r--r--sql/sql_list.h74
3 files changed, 185 insertions, 2 deletions
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 17897b2f549..3c7a74c0c57 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2377,3 +2377,57 @@ table type possible_keys key key_len ref rows Extra
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;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 9be08b8390b..6626397e9e5 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1924,3 +1924,62 @@ EXPLAIN SELECT * FROM t1 LEFT JOIN t2 USE INDEX (a) ON t1.a=t2.a;
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;
+
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 370642df2d0..9e62b7ce730 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -110,10 +110,32 @@ public:
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.
+ The other way to fix this would be to change this function to
+ remove_next() and have base_list_iterator save ptr to previous node
+ (one extra assignment in iterator++) but as the remove() of the last
+ element isn't a common operation it's faster to just walk through the
+ list from the beginning here.
+ */
+ 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)
{
@@ -130,6 +152,54 @@ public:
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
+ check_list()
+ name Name to print to trace file
+
+ RETURN
+ 1 The list is Ok.
+ 0 List invariants are not met.
+ */
+
+ bool check_list(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)
{