--- database.inc 2008-07-09 23:48:28.000000000 +0200 +++ database.inc 2008-07-18 12:37:48.000000000 +0200 @@ -320,31 +320,25 @@ } if (!empty($where) || !empty($join)) { - $pattern = '{ - # Beginning of the string - ^ - ((?P - # Everything within this set of parentheses is named "anonymous view" - (?: - [^()]++ # anything not parentheses - | - \( (?P>anonymous_view) \) # an open parenthesis, more "anonymous view" and finally a close parenthesis. - )* - )[^()]+WHERE) - }x'; - preg_match($pattern, $query, $matches); if (!$where) { $where = '1 = 1'; } + $no_inner_wheres = $query; + // Hide parentheses and inner "WHERE"s, while preserving the string length. + // $no_inner_wheres will be invalid SQL, it only helps us find the right WHERE position. + do { // Repeat to handle nested parentheses (one level at a time, from inside and out) + $previous = $no_inner_wheres; + $no_inner_wheres = preg_replace(array('/\(([^()]*)\bWHERE\b([^()]*)\)/', '/\(([^()]*)\)/'), array('[$1#####$2]', '[$1]'), $no_inner_wheres); + } while ($no_inner_wheres != $previous); + preg_match('/\bWHERE\b/', $no_inner_wheres, $matches, PREG_OFFSET_CAPTURE); if ($matches) { - $n = strlen($matches[1]); - $second_part = substr($query, $n); - $first_part = substr($matches[1], 0, $n - 5) ." $join WHERE $where AND ( "; + $first_part = substr($query, 0, $matches[0][1]) ." $join WHERE $where AND ( "; + $second_part = substr($query, $matches[0][1] + 5); // PHP 4 does not support strrpos for strings. We emulate it. $haystack_reverse = strrev($second_part); } else { - $haystack_reverse = strrev($query); + $haystack_reverse = strrev($no_inner_wheres); } // No need to use strrev on the needle, we supply GROUP, ORDER, LIMIT // reversed.