diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 387e7eff693..38ebd26abe4 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2454,4 +2454,58 @@ select all distinct * from t1; ERROR HY000: Incorrect usage of ALL and DISTINCT select distinct all * from t1; ERROR HY000: Incorrect usage of ALL and DISTINCT +DROP TABLE t1; +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 a46522c1510..0634323cef7 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1950,7 +1950,6 @@ EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a; DROP TABLE t1, t2; - # # Test case for bug 7098: substitution of a constant for a string field # @@ -1993,5 +1992,62 @@ select all distinct * from t1; select distinct all * from t1; drop table t1; - # +# 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 45a6b5066eb..e799ecf3d6e 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -129,10 +129,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 concat(base_list *list) { @@ -162,6 +184,54 @@ public: friend class error_list; friend class error_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) { diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 661bf6e8197..7157111b25c 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -193,7 +193,9 @@ void udf_init() This is done to ensure that only approved dll from the system directories are used (to make this even remotely secure). */ - if (strchr(dl_name, '/') || name.length > NAME_LEN) + if (strchr(dl_name, '/') || + IF_WIN(strchr(dl_name, '\\'),0) || + strlen(name) > NAME_LEN) { sql_print_error("Invalid row in mysql.func table for function '%.64s'", name.str); @@ -222,7 +224,7 @@ void udf_init() } tmp->dlhandle = dl; { - char buf[MAX_FIELD_NAME+16], *missing; + char buf[NAME_LEN+16], *missing; if ((missing= init_syms(tmp, buf))) { sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), missing); @@ -409,7 +411,7 @@ int mysql_create_function(THD *thd,udf_func *udf) This is done to ensure that only approved dll from the system directories are used (to make this even remotely secure). */ - if (strchr(udf->dl, '/')) + if (strchr(udf->dl, '/') || IF_WIN(strchr(dl_name, '\\'),0)) { send_error(thd, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS)); DBUG_RETURN(1); @@ -439,7 +441,7 @@ int mysql_create_function(THD *thd,udf_func *udf) } udf->dlhandle=dl; { - char buf[MAX_FIELD_NAME+16], *missing; + char buf[NAME_LEN+16], *missing; if ((missing= init_syms(udf, buf))) { net_printf(thd, ER_CANT_FIND_DL_ENTRY, missing); diff --git a/sql/unireg.cc b/sql/unireg.cc index 72960640b1b..e6484a9c1c2 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -27,6 +27,7 @@ #define USES_TYPES #include "mysql_priv.h" #include +#include #define FCOMP 17 /* Bytes for a packed field */