Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.257 diff -u -F^f -r1.257 search.module --- modules/search/search.module 14 May 2008 15:07:25 -0000 1.257 +++ modules/search/search.module 15 May 2008 20:21:07 -0000 @@ -913,46 +913,83 @@ function _search_parse_query(&$word, &$s * @ingroup search */ function do_search($keywords, $type, $join1 = '', $where1 = '1', $arguments1 = array(), $columns2 = 'i.relevance AS score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY score DESC') { - $query = search_parse_query($keywords); + list($phrase_query, $phrase_arguments, $keyword_query, $keyword_arguments, $matches, $simple, $warning) = search_parse_query($keywords); - if ($query[2] == '') { - form_set_error('keys', t('You must include at least one positive keyword with @count characters or more.', array('@count' => variable_get('minimum_word_size', 3)))); + // If nothing is being searched for, get out of here. + if ($phrase_query == '' || $keyword_query == '') { + return array(); } - if ($query[6]) { - if ($query[6] == 'or') { - drupal_set_message(t('Search for either of the two terms with uppercase OR. For example, cats OR dogs.')); + + // Calculate maximum keyword relevance, to normalize it. + // Start with a COUNT query. + $count_arguments = $keyword_arguments1; + $count_joins = array($join1); + $count_wheres = array($where1); + + if ($keyword_query) { + $count_wheres[] = "($keyword_query)"; + foreach ($keyword_arguments as $argument) { + $count_arguments[] = $argument; } } - if ($query === NULL || $query[0] == '' || $query[2] == '') { + $count_wheres[] = "i.type = '%s'"; + $count_arguments[] = $type; + if (!$simple) { + // Complex queries have a JOIN and WHERE for phrases plus extra arguments + $count_joins[] = 'INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type'; + foreach ($phrase_arguments as $argument) { + $count_arguments[] = $argument; + } + $count_wheres[] = "($phrase_query)"; + } + $count_arguments[] = $matches; + + $count_join = implode(' ', $count_joins); + $count_where = implode(' AND ', $count_wheres); + + // Execute the count query before the main query. + $count = db_result(db_query("SELECT COUNT(*) FROM (SELECT 1 FROM {search_index} i $count_join WHERE $count_where GROUP BY i.type, i.sid HAVING COUNT(*) >= %d) n1", $count_arguments)); + // If there aren't any results, return empty. + if ($count == 0) { return array(); } + // Build the simplest of all queries for db_pager(). + $count_select = "SELECT $count"; // Build query for keyword normalization. - $conditions = "$where1 AND ($query[2]) AND i.type = '%s'"; - $arguments1 = array_merge($arguments1, $query[3], array($type)); - $join = "INNER JOIN {search_total} t ON i.word = t.word $join1"; - if (!$query[5]) { - $conditions .= " AND ($query[0])"; - $arguments1 = array_merge($arguments1, $query[1]); - $join .= " INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type"; + $query_arguments = $arguments1; + $query_joins = array("INNER JOIN {search_total} t ON i.word = t.word", $join1); + $query_wheres = array($where1, "($keyword_query)", "i.type = '%s'"); + + foreach ($keyword_arguments as $argument) { + $query_arguments[] = $argument; + } + $query_arguments[] = $type; + + if (!$simple) { + $query_wheres[] = "($phrase_query)"; + foreach ($phrase_arguments as $argument) { + $query_arguments[] = $argument; + } + $query_joins[] = "INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type"; } - // Calculate maximum keyword relevance, to normalize it. - $select = "SELECT SUM(i.score * t.count) AS score FROM {search_index} i $join WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d ORDER BY score DESC"; - $arguments = array_merge($arguments1, array($query[4])); - $normalize = db_result(db_query_range($select, $arguments, 0, 1)); + $query_arguments[] = $matches; + $query_join = implode(' ', $query_joins); + $query_where = implode(' AND ', $query_wheres); + + $select = "SELECT SUM(i.score * t.count) AS score FROM {search_index} i $query_join WHERE $query_where GROUP BY i.type, i.sid HAVING COUNT(*) >= %d ORDER BY score DESC"; + $normalize = db_result(db_query_range($select, $query_arguments, 0, 1)); if (!$normalize) { return array(); } - $columns2 = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * SUM(i.score * t.count))', $columns2); // Build query to retrieve results. - $select = "SELECT i.type, i.sid, $columns2 FROM {search_index} i $join $join2 WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d"; - $count_select = "SELECT COUNT(*) FROM ($select) n1"; - $arguments = array_merge($arguments2, $arguments1, array($query[4])); - + $columns2 = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * SUM(i.score * t.count))', $columns2); + $select = "SELECT i.type, i.sid, $columns2 FROM {search_index} i $query_join $join2 WHERE $query_where GROUP BY i.type, i.sid HAVING COUNT(*) >= %d"; + // Do actual search query - $result = pager_query("$select $sort_parameters", 10, 0, $count_select, $arguments); + $result = pager_query("$select $sort_parameters", 10, 0, $count_select, array_merge($arguments2, $query_arguments)); $results = array(); while ($item = db_fetch_object($result)) { $results[] = $item;