diff options
author | Gábor Hojtsy <gabor@hojtsy.hu> | 2008-01-08 16:03:31 +0000 |
---|---|---|
committer | Gábor Hojtsy <gabor@hojtsy.hu> | 2008-01-08 16:03:31 +0000 |
commit | 1ac7418865dde2a0d1f5bfafa9663a88366ca5e0 (patch) | |
tree | a8ab38c12a6daaec5333e812f0e5bff6158c33dc | |
parent | 00f0a95adedf24f3b172989173262a0d2ec7dc96 (diff) | |
download | brdo-1ac7418865dde2a0d1f5bfafa9663a88366ca5e0.tar.gz brdo-1ac7418865dde2a0d1f5bfafa9663a88366ca5e0.tar.bz2 |
#151910 by chx: support subqueries in db_rewrite_sql() - now that we use subqueries even in core, this was critical
-rw-r--r-- | includes/database.inc | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/includes/database.inc b/includes/database.inc index c8212c16f..d3de06cd8 100644 --- a/includes/database.inc +++ b/includes/database.inc @@ -315,34 +315,44 @@ function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $ } if (!empty($where) || !empty($join)) { - if (!empty($where)) { - $new = "WHERE $where "; - } - $new = " $join $new"; - if (strpos($query, 'WHERE')) { - $query = str_replace('WHERE', $new .'AND (', $query); - $insert = ') '; - } - else { - $insert = $new; - } - if (strpos($query, 'GROUP')) { - $replace = 'GROUP'; - } - elseif (strpos($query, 'HAVING')) { - $replace = 'HAVING'; - } - elseif (strpos($query, 'ORDER')) { - $replace = 'ORDER'; - } - elseif (strpos($query, 'LIMIT')) { - $replace = 'LIMIT'; + $pattern = '{ + # Beginning of the string + ^ + ((?P<anonymous_view> + # 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) { + $n = strlen($matches[1]); + $second_part = substr($query, $n); + $first_part = substr($matches[1], 0, $n - 5) ." $join WHERE $where AND ( "; + // PHP 4 does not support strrpos for strings. We emulate it. + $haystack_reverse = strrev($second_part); + // No need to use strrev on the needle, we supply GROUP, ORDER, LIMIT + // reversed. + foreach (array('PUORG', 'REDRO', 'TIMIL') as $needle_reverse) { + $pos = strpos($haystack_reverse, $needle_reverse); + if ($pos !== FALSE) { + // All needles are five characters long. + $pos += 5; + break; + } + } + if ($pos === FALSE) { + $query = $first_part . $second_part .')'; + } + else { + $query = $first_part . substr($second_part, 0, -$pos) .')'. substr($second_part, -$pos); + } } else { - $query .= $insert; - } - if (isset($replace)) { - $query = str_replace($replace, $insert . $replace, $query); + $query = $matches[1] ." $join ". substr($query, strlen($matches[1])); } } |