Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.708
diff -u -p -r1.708 comment.module
--- modules/comment/comment.module 3 May 2009 10:11:34 -0000 1.708
+++ modules/comment/comment.module 11 May 2009 20:22:26 -0000
@@ -2236,10 +2236,15 @@ function comment_ranking() {
return array(
'comments' => array(
'title' => t('Number of comments'),
- 'join' => 'LEFT JOIN {node_comment_statistics} node_comment_statistics ON node_comment_statistics.nid = i.sid',
+ 'join' => array(
+ 'type' => 'LEFT OUTER',
+ 'table' => 'node_comment_statistics',
+ 'alias' => 'node_comment_statistics',
+ 'on' => 'node_comment_statistics.nid = i.sid',
+ ),
// Inverse law that maps the highest reply count on the site to 1 and 0 to 0.
- 'score' => '2.0 - 2.0 / (1.0 + node_comment_statistics.comment_count * CAST(%f AS DECIMAL))',
- 'arguments' => array(variable_get('node_cron_comments_scale', 0)),
+ 'score' => '2.0 - 2.0 / (1.0 + node_comment_statistics.comment_count * CAST(:scale AS DECIMAL))',
+ 'arguments' => array(':scale' => variable_get('node_cron_comments_scale', 0)),
),
);
}
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1045
diff -u -p -r1.1045 node.module
--- modules/node/node.module 9 May 2009 18:28:12 -0000 1.1045
+++ modules/node/node.module 11 May 2009 20:22:34 -0000
@@ -1369,20 +1369,22 @@ function _node_rankings() {
$rankings = array(
'total' => 0, 'join' => array(), 'score' => array(), 'args' => array(),
);
+ $i = 0;
if ($ranking = module_invoke_all('ranking')) {
foreach ($ranking as $rank => $values) {
if ($node_rank = variable_get('node_rank_'. $rank, 0)) {
// If the table defined in the ranking isn't already joined, then add it.
- if (isset($values['join']) && !isset($rankings['join'][$values['join']])) {
- $rankings['join'][$values['join']] = $values['join'];
+ if (isset($values['join']) && !isset($rankings['join'][$values['join']['alias']])) {
+ $rankings['join'][$values['join']['alias']] = $values['join'];
}
// Add the rankings weighted score multiplier value, handling NULL gracefully.
- $rankings['score'][] = 'CAST(%f AS DECIMAL) * COALESCE(('. $values['score'] .'), 0)';
+ $rankings['score'][] = "CAST(:node_rank_$i AS DECIMAL) * COALESCE(( " . $values['score'] .'), 0)';
// Add the the administrator's weighted score multiplier value for this ranking.
$rankings['total'] += $node_rank;
- $rankings['arguments'][] = $node_rank;
+ $rankings['arguments'][':node_rank_' . $i] = $node_rank;
+ $i++;
// Add any additional arguments used by this ranking.
if (isset($values['arguments'])) {
@@ -1441,38 +1443,37 @@ function node_search($op = 'search', $ke
case 'search':
// Build matching conditions
- list($join1, $where1) = _db_rewrite_sql();
- $arguments1 = array();
- $conditions1 = 'n.status = 1';
+ $query = db_select('search_index', 'i');
+ $query->join('node', 'n', 'n.nid = i.sid');
+ $query
+ ->condition('n.status', 1)
+ ->addTag('node_access');
if ($type = search_query_extract($keys, 'type')) {
- $types = array();
+ $types_or = db_or();
foreach (explode(',', $type) as $t) {
- $types[] = "n.type = '%s'";
- $arguments1[] = $t;
+ $types_or->condition('n.type', $t);
}
- $conditions1 .= ' AND (' . implode(' OR ', $types) . ')';
+ $query->condition($types_or);
$keys = search_query_insert($keys, 'type');
}
if ($term = search_query_extract($keys, 'term')) {
- $terms = array();
+ $term_or = db_or();
foreach (explode(',', $term) as $c) {
- $terms[] = "tn.tid = %d";
- $arguments1[] = $c;
+ $term_or->condition('tn.nid', $c);
}
- $conditions1 .= ' AND (' . implode(' OR ', $terms) . ')';
- $join1 .= ' INNER JOIN {taxonomy_term_node} tn ON n.vid = tn.vid';
+ $query->condition($term_or);
+ $query->join('taxonomy_term_node', 'tn', 'n.vid = tn.vid');
$keys = search_query_insert($keys, 'term');
}
if ($languages = search_query_extract($keys, 'language')) {
- $terms = array();
+ $lang_or = db_or();
foreach (explode(',', $languages) as $l) {
- $terms[] = "n.language = '%s'";
- $arguments1[] = $l;
+ $lang_or->condition('n.language', $l);
}
- $conditions1 .= ' AND (' . implode(' OR ', $terms) . ')';
+ $query->condition($lang_or);
$keys = search_query_insert($keys, 'language');
}
@@ -1481,21 +1482,17 @@ function node_search($op = 'search', $ke
// When all search factors are disabled (ie they have a weight of zero),
// The default score is based only on keyword relevance.
- if ($rankings['total'] == 0) {
- $total = 1;
- $arguments2 = array();
- $join2 = '';
- $select2 = 'SUM(i.relevance) AS calculated_score';
- }
- else {
+ $total = 0;
+ if ($rankings['total'] != 0) {
$total = $rankings['total'];
- $arguments2 = $rankings['arguments'];
- $join2 = implode(' ', $rankings['join']);
- $select2 = 'SUM('. implode(' + ', $rankings['score']) .') AS calculated_score';
+ foreach ($rankings['join'] as $join) {
+ $query->addJoin($join['type'], $join['table'], $join['alias'], $join['on']);
+ }
+ $query->addExpression('SUM('. implode(' + ', $rankings['score']) . ')', 'calculated_score', $rankings['arguments']);
}
// Do search.
- $find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid ' . $join1, $conditions1 . (empty($where1) ? '' : ' AND ' . $where1), $arguments1, $select2, $join2, $arguments2);
+ $find = do_search($keys, 'node', $query);
// Load results.
$results = array();
@@ -1557,8 +1554,8 @@ function node_ranking() {
$ranking['recent'] = array(
'title' => t('Recently posted'),
// Exponential decay with half-life of 6 months, starting at last indexed node
- 'score' => 'POW(2.0, (GREATEST(n.created, n.changed) - %d) * 6.43e-8)',
- 'arguments' => array($node_cron_last),
+ 'score' => 'POW(2.0, (GREATEST(n.created, n.changed) - :node_cron_last) * 6.43e-8)',
+ 'arguments' => array(':node_cron_last' => $node_cron_last),
);
}
return $ranking;
Index: modules/search/search.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.api.php,v
retrieving revision 1.7
diff -u -p -r1.7 search.api.php
--- modules/search/search.api.php 9 May 2009 10:45:57 -0000 1.7
+++ modules/search/search.api.php 11 May 2009 20:22:35 -0000
@@ -76,12 +76,15 @@ function hook_search($op = 'search', $ke
return t('Content');
case 'reset':
- db_query("UPDATE {search_dataset} SET reindex = %d WHERE type = 'node'", REQUEST_TIME);
+ db_update('search_dataset')
+ ->fields(array('reindex' => REQUEST_TIME))
+ ->condition('type', 'node')
+ ->execute();
return;
case 'status':
- $total = db_result(db_query('SELECT COUNT(*) FROM {node} WHERE status = 1'));
- $remaining = db_result(db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0"));
+ $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField();
+ $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
return array('remaining' => $remaining, 'total' => $total);
case 'admin':
@@ -248,7 +251,11 @@ function hook_update_index() {
$last = variable_get('node_cron_last', 0);
$limit = (int)variable_get('search_cron_limit', 100);
- $result = db_query_range('SELECT n.nid, c.last_comment_timestamp FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND n.moderate = 0 AND (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d) ORDER BY GREATEST(n.created, n.changed, c.last_comment_timestamp) ASC', $last, $last, $last, 0, $limit);
+ $result = db_query_range('SELECT n.nid, c.last_comment_timestamp FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND n.moderate = 0 AND (n.created > :created OR n.changed > :changed OR c.last_comment_timestamp > :comment) ORDER BY GREATEST(n.created, n.changed, c.last_comment_timestamp) ASC', array(
+ ':created' => $last,
+ ':changed' => $last,
+ ':comment' => $last,
+ ), 0, $limit);
while ($node = db_fetch_object($result)) {
$last_comment = $node->last_comment_timestamp;
Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.289
diff -u -p -r1.289 search.module
--- modules/search/search.module 6 May 2009 10:48:01 -0000 1.289
+++ modules/search/search.module 11 May 2009 20:22:39 -0000
@@ -248,11 +248,20 @@ function search_wipe($sid = NULL, $type
module_invoke_all('search', 'reset');
}
else {
- db_query("DELETE FROM {search_dataset} WHERE sid = %d AND type = '%s'", $sid, $type);
- db_query("DELETE FROM {search_index} WHERE sid = %d AND type = '%s'", $sid, $type);
+ db_delete('search_dataset')
+ ->condition('sid', $sid)
+ ->condition('type', $type)
+ ->execute();
+ db_delete('search_index')
+ ->condition('sid', $sid)
+ ->condition('type', $type)
+ ->execute();
// Don't remove links if re-indexing.
if (!$reindex) {
- db_query("DELETE FROM {search_node_links} WHERE sid = %d AND type = '%s'", $sid, $type);
+ db_delete('search_node_links')
+ ->condition('sid', $sid)
+ ->condition('type', $type)
+ ->execute();
}
}
}
@@ -295,7 +304,7 @@ function search_update_totals() {
// Update word IDF (Inverse Document Frequency) counts for new/changed words
foreach (search_dirty() as $word => $dummy) {
// Get total count
- $total = db_result(db_query("SELECT SUM(score) FROM {search_index} WHERE word = '%s'", $word));
+ $total = db_query("SELECT SUM(score) FROM {search_index} WHERE word = :word", array(':word' => $word))->fetchField();
// Apply Zipf's law to equalize the probability distribution
$total = log10(1 + 1/(max(1, $total)));
db_merge('search_total')->key(array('word' => $word))->fields(array('count' => $total))->execute();
@@ -304,8 +313,14 @@ function search_update_totals() {
// search_total. We use a LEFT JOIN between the two tables and keep only the
// rows which fail to join.
$result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL");
- while ($word = db_fetch_object($result)) {
- db_query("DELETE FROM {search_total} WHERE word = '%s'", $word->realword);
+ $or = db_or();
+ foreach ($result as $word) {
+ $or->condition('word', $word->realword);
+ }
+ if (count($or) > 0) {
+ db_delete('search_total')
+ ->condition($or)
+ ->execute();
}
}
@@ -512,7 +527,7 @@ function search_index($sid, $type, $text
$linknid = $match[1];
if ($linknid > 0) {
// Note: ignore links to uncachable nodes to avoid redirect bugs.
- $node = db_fetch_object(db_query('SELECT n.title, n.nid, n.vid, r.format FROM {node} n INNER JOIN {node_revision} r ON n.vid = r.vid WHERE n.nid = %d', $linknid));
+ $node = db_query('SELECT n.title, n.nid, n.vid, r.format FROM {node} n INNER JOIN {node_revision} r ON n.vid = r.vid WHERE n.nid = :nid', array(':nid' => $linknid))->fetchAssoc();
if (filter_format_allowcache($node->format)) {
$link = TRUE;
$linktitle = $node->title;
@@ -580,7 +595,14 @@ function search_index($sid, $type, $text
search_wipe($sid, $type, TRUE);
// Insert cleaned up data into dataset
- db_query("INSERT INTO {search_dataset} (sid, type, data, reindex) VALUES (%d, '%s', '%s', %d)", $sid, $type, $accum, 0);
+ db_insert('search_dataset')
+ ->fields(array(
+ 'sid' => $sid,
+ 'type' => $type,
+ 'data' => $accum,
+ 'reindex' => 0,
+ ))
+ ->execute();
// Insert results into search index
foreach ($results[0] as $word => $score) {
@@ -588,19 +610,24 @@ function search_index($sid, $type, $text
// appropriately. If not, we create a new record with the appropriate
// starting score.
db_merge('search_index')->key(array(
- 'word' => $word,
- 'sid' => $sid,
- 'type' => $type,
- ))->fields(array('score' => $score))->expression('score', 'score + :score', array(':score' => $score))
- ->execute();
+ 'word' => $word,
+ 'sid' => $sid,
+ 'type' => $type,
+ ))
+ ->fields(array('score' => $score))
+ ->expression('score', 'score + :score', array(':score' => $score))
+ ->execute();
search_dirty($word);
}
unset($results[0]);
// Get all previous links from this item.
- $result = db_query("SELECT nid, caption FROM {search_node_links} WHERE sid = %d AND type = '%s'", $sid, $type);
+ $result = db_query("SELECT nid, caption FROM {search_node_links} WHERE sid = :sid AND type = :type", array(
+ ':sid' => $sid,
+ ':type' => $type
+ ));
$links = array();
- while ($link = db_fetch_object($result)) {
+ foreach ($result as $link) {
$links[$link->nid] = $link->caption;
}
@@ -610,7 +637,12 @@ function search_index($sid, $type, $text
if (isset($links[$nid])) {
if ($links[$nid] != $caption) {
// Update the existing link and mark the node for reindexing.
- db_query("UPDATE {search_node_links} SET caption = '%s' WHERE sid = %d AND type = '%s' AND nid = %d", $caption, $sid, $type, $nid);
+ db_update('search_node_links')
+ ->fields(array('caption' => $caption))
+ ->condition('sid', $sid)
+ ->condition('type', $type)
+ ->condition('nid', $nid)
+ ->execute();
search_touch_node($nid);
}
// Unset the link to mark it as processed.
@@ -618,13 +650,24 @@ function search_index($sid, $type, $text
}
else {
// Insert the existing link and mark the node for reindexing.
- db_query("INSERT INTO {search_node_links} (caption, sid, type, nid) VALUES ('%s', %d, '%s', %d)", $caption, $sid, $type, $nid);
+ db_insert('search_node_links')
+ ->fields(array(
+ 'caption' => $caption,
+ 'sid' => $sid,
+ 'type' => $type,
+ 'nid' => $nid,
+ ))
+ ->execute();
search_touch_node($nid);
}
}
// Any left-over links in $links no longer exist. Delete them and mark the nodes for reindexing.
foreach ($links as $nid => $caption) {
- db_query("DELETE FROM {search_node_links} WHERE sid = %d AND type = '%s' AND nid = %d", $sid, $type, $nid);
+ db_delete('search_node_links')
+ ->condition('sid', $sid)
+ ->condition('type', $type)
+ ->condition('nid', $nid)
+ ->execute();
search_touch_node($nid);
}
}
@@ -636,7 +679,11 @@ function search_index($sid, $type, $text
* The nid of the node that needs reindexing.
*/
function search_touch_node($nid) {
- db_query("UPDATE {search_dataset} SET reindex = %d WHERE sid = %d AND type = 'node'", REQUEST_TIME, $nid);
+ db_update('search_dataset')
+ ->fields(array('reindex' => REQUEST_TIME))
+ ->condition('type', 'node')
+ ->condition('sid', $nid)
+ ->execute();
}
/**
@@ -644,9 +691,9 @@ function search_touch_node($nid) {
*/
function search_node_update_index($node) {
// Transplant links to a node into the target node.
- $result = db_query("SELECT caption FROM {search_node_links} WHERE nid = %d", $node->nid);
+ $result = db_query("SELECT caption FROM {search_node_links} WHERE nid = :nid", array(':nid' => $node->nid));
$output = array();
- while ($link = db_fetch_object($result)) {
+ foreach ($result as $link) {
$output[] = $link->caption;
}
if (count($output)) {
@@ -811,10 +858,8 @@ function search_parse_query($text) {
}
// Convert keywords into SQL statements.
- $query = array();
- $query2 = array();
- $arguments = array();
- $arguments2 = array();
+ $words = array();
+ $conditions = db_and();
$matches = 0;
$simple_and = FALSE;
$simple_or = FALSE;
@@ -823,18 +868,15 @@ function search_parse_query($text) {
// Group of ORed terms
if (is_array($key) && count($key)) {
$simple_or = TRUE;
- $queryor = array();
$any = FALSE;
+ $queryor = db_or();
foreach ($key as $or) {
- list($q, $num_new_scores) = _search_parse_query($or, $arguments2);
+ list($num_new_scores) = _search_parse_query($or, $words);
$any |= $num_new_scores;
- if ($q) {
- $queryor[] = $q;
- $arguments[] = "% $or %";
- }
+ $queryor->condition('d.data', "% $or %", 'LIKE');
}
if (count($queryor)) {
- $query[] = '(' . implode(' OR ', $queryor) . ')';
+ $conditions->condition($queryor);
// A group of OR keywords only needs to match once
$matches += ($any > 0);
}
@@ -842,16 +884,13 @@ function search_parse_query($text) {
// Single ANDed term
else {
$simple_and = TRUE;
- list($q, $num_new_scores, $num_valid_words) = _search_parse_query($key, $arguments2);
- if ($q) {
- $query[] = $q;
- $arguments[] = "% $key %";
- if (!$num_valid_words) {
- $simple = FALSE;
- }
- // Each AND keyword needs to match at least once
- $matches += $num_new_scores;
+ list($num_new_scores, $num_valid_words) = _search_parse_query($key, $words);
+ $conditions->condition('d.data', "% $key %", 'LIKE');
+ if (!$num_valid_words) {
+ $simple = FALSE;
}
+ // Each AND keyword needs to match at least once
+ $matches += $num_new_scores;
}
}
if ($simple_and && $simple_or) {
@@ -859,19 +898,12 @@ function search_parse_query($text) {
}
// Negative matches
foreach ($keys['negative'] as $key) {
- list($q) = _search_parse_query($key, $arguments2, TRUE);
- if ($q) {
- $query[] = $q;
- $arguments[] = "% $key %";
- $simple = FALSE;
- }
+ $conditions->condition('d.data', "% $key %", 'NOT LIKE');
+ $simple = FALSE;
}
- $query = implode(' AND ', $query);
// Build word-index conditions for the first pass
- $query2 = substr(str_repeat("i.word = '%s' OR ", count($arguments2)), 0, -4);
-
- return array($query, $arguments, $query2, $arguments2, $matches, $simple, $warning);
+ return array($conditions, $words, $matches, $simple, $warning);
}
/**
@@ -896,7 +928,7 @@ function _search_parse_query(&$word, &$s
}
}
// Return matching snippet and number of added words
- return array("d.data " . ($not ? 'NOT ' : '') . "LIKE '%s'", $num_new_scores, $num_valid_words);
+ return array($num_new_scores, $num_valid_words);
}
/**
@@ -913,7 +945,10 @@ function _search_parse_query(&$word, &$s
* of also providing the exact result set for simple "AND" or "OR" searches.
*
* The second portion of the query further refines this set by verifying
- * advanced text conditions (such negative or phrase matches)
+ * advanced text conditions (such negative or phrase matches).
+ *
+ * The used query object has the tag 'search_$type' and can be further extend
+ * with hook_query_alter().
*
* @param $keywords
* A search string as entered by the user.
@@ -921,84 +956,111 @@ function _search_parse_query(&$word, &$s
* @param $type
* A string identifying the calling module.
*
- * @param $join1
- * (optional) Inserted into the JOIN part of the first SQL query.
- * For example "INNER JOIN {node} n ON n.nid = i.sid".
- *
- * @param $where1
- * (optional) Inserted into the WHERE part of the first SQL query.
- * For example "(n.status > %d)".
- *
- * @param $arguments1
- * (optional) Extra SQL arguments belonging to the first query.
- *
- * @param $columns2
- * (optional) Inserted into the SELECT pat of the second query. Must contain
- * a column selected as 'calculated_score'.
- * defaults to 'SUM(i.relevance) AS calculated_score'
- *
- * @param $join2
- * (optional) Inserted into the JOIN par of the second SQL query.
- * For example "INNER JOIN {node_comment_statistics} n ON n.nid = i.sid"
- *
- * @param $arguments2
- * (optional) Extra SQL arguments belonging to the second query parameter.
- *
- * @param $sort_parameters
- * (optional) SQL arguments for sorting the final results.
- * Default: 'ORDER BY calculated_score DESC'
+ * @param $query
+ * A SelectQuery object that is used instead of the default value.
+ *
+ * This will be cloned and used for both steps of the search passes.
+ * However, expressions will be not be used in the first pass, they only apply
+ * for the second pass.
+ *
+ * Default value:
+ * $query = db_select('search_index', 'i');
*
* @return
* An array of SIDs for the search results.
*
* @ingroup search
*/
-function do_search($keywords, $type, $join1 = '', $where1 = '1 = 1', $arguments1 = array(), $columns2 = 'SUM(i.relevance) AS calculated_score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY calculated_score DESC') {
- $query = search_parse_query($keywords);
+function do_search($keywords, $type, SelectQueryInterface $query = NULL) {
+ if (is_null($query)) {
+ $query = db_select('search_index', 'i');
+ }
+ list($conditions, $words, $matches, $simple, $warning) = search_parse_query($keywords);
- if ($query[2] == '') {
+ if (count($words) == 0) {
form_set_error('keys', format_plural(variable_get('minimum_word_size', 3), 'You must include at least one positive keyword with 1 character or more.', 'You must include at least one positive keyword with @count characters or more.'));
}
- 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.'));
- }
+ if ($warning == 'or') {
+ drupal_set_message(t('Search for either of the two terms with uppercase OR. For example, cats OR dogs.'));
}
- if ($query === NULL || $query[0] == '' || $query[2] == '') {
+ if (count($conditions) == 0 || count($words) == 0) {
return array();
}
- // 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";
+ if (!empty($words)) {
+ $or = db_or();
+ foreach ($words as $word) {
+ $or->condition('i.word', $word);
+ }
+ $query->condition($or);
}
+ // Build query for keyword normalization.
+ $query->join('search_total', 't', 'i.word = t.word');
+ $query
+ ->condition('i.type', $type)
+ ->groupBy('i.type')
+ ->groupBy('i.sid')
+ ->having('COUNT(*) >= :matches', array(':matches' => $matches));
+ if (!$simple) {
+ $query->condition($conditions);
+ $query->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type');
+ }
+
+ // Create the second query object before adding normalization specific information.
+ $query2 = clone $query;
+
+ // Reset the expressions, for the count query, only the default SUM is necessary
+ $expressions =& $query->getExpressions();
+ $expressions = array();
// Calculate maximum keyword relevance, to normalize it.
- $select = "SELECT SUM(i.score * t.count) AS calculated_score FROM {search_index} i $join WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d ORDER BY calculated_score DESC";
- $arguments = array_merge($arguments1, array($query[4]));
- $normalize = db_result(db_query_range($select, $arguments, 0, 1));
+ $query->addExpression('SUM(i.score * t.count)', 'calculated_score');
+ $normalize = $query
+ ->range(0, 1)
+ ->orderBy('calculated_score', 'DESC')
+ ->execute()
+ ->fetchField();
if (!$normalize) {
return array();
}
- $columns2 = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * 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_values(array_merge($arguments2, $arguments1, array($query[4])));
-
- // Do actual search query
- $result = pager_query("$select $sort_parameters", 10, 0, $count_select, $arguments);
- $results = array();
- while ($item = db_fetch_object($result)) {
- $results[] = $item;
+ // If the search query is simple, add conditions now.
+ // For a complex query, they have been added already.
+ if ($simple) {
+ $query2->condition($conditions);
+ $query2->join('search_dataset', 'd', 'i.sid = d.sid AND i.type = d.type');
+ }
+
+ // Either add default score expression or replace pseudo field i.relevance
+ // with the actual normalization value.
+ if (count($query2->getExpressions()) == 0) {
+ $query2->addExpression('SUM(' . (1.0 / $normalize) . ' * i.score * t.count)', 'calculated_score');
+ } else {
+ $expressions =& $query2->getExpressions();
+ foreach ($expressions as &$expression) {
+ $expression['expression'] = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * i.score * t.count)', $expression['expression']);
+ }
}
- return $results;
+
+ // Add tag and useful metadata.
+ $query2
+ ->addTag('search_' . $type)
+ ->addMetaData('normalize', $normalize);
+
+ // Create count query.
+ $count_query = db_select(clone $query2, 'subquery');
+ $count_query->addExpression('COUNT(*)');
+
+ // Extend the query with the pager and add the count query.
+ $query2 = $query2->extend('PagerDefault');
+ $query2->setCountQuery($count_query);
+
+ return $query2
+ ->fields('i', array('type', 'sid'))
+ ->orderBy('calculated_score', 'DESC')
+ ->limit(10)
+ ->execute()
+ ->fetchAll();
}
/**
Index: modules/statistics/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v
retrieving revision 1.303
diff -u -p -r1.303 statistics.module
--- modules/statistics/statistics.module 3 May 2009 10:11:35 -0000 1.303
+++ modules/statistics/statistics.module 11 May 2009 20:22:49 -0000
@@ -380,10 +380,15 @@ function statistics_ranking() {
return array(
'views' => array(
'title' => t('Number of views'),
- 'join' => 'LEFT JOIN {node_counter} node_counter ON node_counter.nid = i.sid',
+ 'join' => array(
+ 'type' => 'LEFT OUTER',
+ 'table' => 'node_counter',
+ 'alias' => 'node_counter',
+ 'on' => 'node_counter.nid = i.sid',
+ ),
// Inverse law that maps the highest view count on the site to 1 and 0 to 0.
- 'score' => '2.0 - 2.0 / (1.0 + node_counter.totalcount * CAST(%f AS DECIMAL))',
- 'arguments' => array(variable_get('node_cron_views_scale', 0)),
+ 'score' => '2.0 - 2.0 / (1.0 + node_counter.totalcount * CAST(:scale AS DECIMAL))',
+ 'arguments' => array(':scale' => variable_get('node_cron_views_scale', 0)),
),
);
}