I've been working on a Drupal module that generates a search form and presents the results below the form. However, I ran into a strange issue where the database query returned 3 records, and yet, the pager was displaying 9 pagination links.
The code that builds and handles the query looks like this:
-
<?php
-
$query = 'select
-
n.nid,
-
n.title,
-
DATE_FORMAT(FROM_UNIXTIME(n.created), \'%c/%e/%Y\') as created,
-
c.field_product_price_value as price,
-
d.name,
-
t.tid
-
from
-
{node} n
-
left join {node_revisions} r on r.vid = n.vid
-
left join {content_type_galleria_product} c on c.nid = n.nid
-
left join {term_node} t on t.nid = n.nid
-
left join {term_data} d on d.tid = t.tid ';
-
-
$groupby = ' group by n.nid';
-
$clauses[] = 'n.type = \'galleria_product\'';
-
-
foreach($form_values as $key => $value)
-
{
-
if(($key) && ($value != ''))
-
{
-
switch($key)
-
{
-
case 'name':
-
$clauses[] = 'n.title like \'%%'.db_escape_string($value).'%%\'';
-
break;
-
case 'price_range':
-
$clauses[] = 'c.field_product_price_value <= '.db_escape_string($value);
-
break;
-
case 'category':
-
$clauses[] = 't.tid = '.db_escape_string($value);
-
break;
-
case 'created':
-
switch($value)
-
{
-
case 'today':
-
$clauses[] = 'DATE(FROM_UNIXTIME(n.created)) = CURDATE()';
-
break;
-
case 'current_week':
-
$clauses[] = 'WEEK(FROM_UNIXTIME(n.created)) = WEEK(NOW())';
-
break;
-
case 'current_month':
-
$clauses[] = 'MONTH(FROM_UNIXTIME(n.created)) = MONTH(NOW())';
-
break;
-
case 'current_year':
-
$clauses[] = 'YEAR(FROM_UNIXTIME(n.created)) = YEAR(NOW())';
-
break;
-
}
-
break;
-
default:
-
break;
-
}
-
}
-
}
-
-
$limit = 30;
-
);
-
-
$tablesort = tablesort_sql($header);
-
$result = pager_query($query.$groupby.$tablesort, $limit, 0);
-
-
// Retrieve all the data found by the query
-
while($data = db_fetch_array($result))
-
{
-
$current_avg = votingapi_get_voting_results('node', $data['nid'], 'percent', 'vote', 'average');
-
l($data['title'], 'node/'.$data['nid']),
-
'$'.$data['price'],
-
l($data['name'], 'taxonomy/term/'.$data['tid']),
-
$data['created'],
-
);
-
}
-
-
{
-
}
-
-
$output = theme('table', $header, $rows);
-
$output .= theme('pager', null, $limit);
-
?>
After banging my head against the wall for a few hours, I came across a post by Kris Buytaert which explained why I was seeing this problem.
To summarize, the code that produces the pagination links is in pager.inc. Within this code is this bit:
-
<?php
-
-
$count_query = preg_replace(array('/SELECT.*?FROM /As', '/ORDER BY .*/'), array('SELECT COUNT(*) FROM ', ''),$query);
-
-
?>
You'll note that the pattern matching is case insensitive. As my query was written all in lowercase, the pagination code was not matching anything. All I had to do was rewrite the query such that the MySQL keywords were in uppercase.
A bug, to be sure, considering that the SQL Standard does not call for specific case. As pager.inc is part of the Drupal core, hopefully it will get patched and fixed soon.
tags: drupal, module, pager, query
