Commit ef6d2648 authored by drumm's avatar drumm
Browse files

Issue #3117465: Replace project_usage_week_project table with...

Issue #3117465: Replace project_usage_week_project table with project_usage_week_release in usage overview page query
parent b4f4fdd3
......@@ -86,15 +86,9 @@ function project_usage_overview() {
//
// - We need to create a separate column for each week to allow sorting by
// usage in any week (the TableSort extender requires that anything you can
// sort on has a distinct field in the underlying query). However, some
// weeks may not have any usage data, forcing us to use a LEFT JOIN,
// rather than the more efficient INNER JOIN.
// - The LEFT JOINs mean we have to limit the entries in {node} so that
// we're not including things like forum posts, hence the WHERE IN below.
// - Each project may have multiple records in {project_usage_week_project}
// to track usage for API version. We need to SUM() them to get a total
// count forcing us to GROUP BY. Sadly, I can't explain why we need
// SUM(DISTINCT)... it just works(TM).
// sort on has a distinct field in the underlying query).
// - Each project will have multiple records in {project_usage_week_release}.
// We SUM() them, with each week’s timestamp, to get a total counts.
//
// Also, because the machine_name is an entity field, and there's no clean
// way to work that into an SQL query, then:
......@@ -108,78 +102,79 @@ function project_usage_overview() {
'data' => t('Project'),
),
);
$rows = array();
$usage_week_nids = db_query('SELECT DISTINCT(nid) FROM {project_usage_week_project}')->fetchCol();
if (!empty($usage_week_nids)) {
$query = db_select('node', 'n')
->fields('n', array('nid', 'title'))
->condition('n.nid', $usage_week_nids, 'IN')
->condition('n.status', NODE_PUBLISHED)
->groupBy('n.nid')
->groupBy('n.title')
->addTag('node_access');
foreach ($weeks as $i => $week) {
// Note that "{$i}" in these query snippets are used to add a week integer
// to the table and field aliases so we can uniquely identify each column
// for sorting purposes.
$query->addExpression("SUM(DISTINCT p{$i}.count)", "week{$i}");
$query->leftJoin('project_usage_week_project', "p{$i}", "n.nid = p{$i}.nid AND p{$i}.timestamp = :timestamp{$i}", array(":timestamp{$i}" => $week));
$header = array(
'field' => "week{$i}",
'data' => format_date($week, 'custom', variable_get('project_usage_date_short', PROJECT_USAGE_DATE_SHORT)),
'class' => array('project-usage-numbers'),
);
if ($i == 0) {
$header['sort'] = 'desc';
}
$headers[] = $header;
$query = db_select('node', 'n')
->fields('n', ['nid', 'title'])
->condition('n.status', NODE_PUBLISHED)
->groupBy('n.nid')
->addTag('node_access');
$query->innerJoin('project_usage_week_release', 'u', 'u.project_nid = n.nid AND timestamp >= :min_week', [
':min_week' => min($weeks),
]);
foreach ($weeks as $i => $week) {
// Note that "{$i}" in these query snippets are used to add a week integer
// to the table and field aliases so we can uniquely identify each column
// for sorting purposes.
$query->addExpression("SUM((u.timestamp = :week{$i}) * u.count)", "week{$i}", [
":week{$i}" => $week,
]);
$header = [
'field' => "week{$i}",
'data' => format_date($week, 'custom', variable_get('project_usage_date_short', PROJECT_USAGE_DATE_SHORT)),
'class' => ['project-usage-numbers'],
];
if ($i == 0) {
$header['sort'] = 'desc';
}
$headers[] = $header;
}
// Check for a cached page. The cache id needs to take into account the sort
// column and order.
$sort = tablesort_init($headers);
$cid = 'overview:' . $sort['sql'] . ':' . $sort['sort'] . ':' . pager_find_page();
$items_per_page = 100;
if ($cached = cache_get($cid, 'cache_project_usage')) {
$rows = $cached->data;
if ($total = cache_get('overview:total', 'cache_project_usage')) {
pager_default_initialize($total->data, $items_per_page);
}
// Check for a cached page. The cache id needs to take into account the sort
// column and order.
$sort = tablesort_init($headers);
$cid = 'overview:' . $sort['sql'] . ':' . $sort['sort'] . ':' . pager_find_page();
$items_per_page = 100;
if ($cached = cache_get($cid, 'cache_project_usage')) {
$rows = $cached->data;
if ($total = cache_get('overview:total', 'cache_project_usage')) {
pager_default_initialize($total->data, $items_per_page);
}
else {
$result = $query
->extend('TableSort')
->orderByHeader($headers)
->extend('PagerDefault')
->limit($items_per_page)
->execute();
$number = pager_find_page() * $items_per_page + 1;
$rows = array();
foreach ($result as $line) {
$machine_name = field_get_items('node', node_load($line->nid, NULL, TRUE), 'field_project_machine_name');
$row = array(
array('data' => $number++),
array('data' => l($line->title, 'project/usage/' . $machine_name[0]['value'])),
);
foreach ($weeks as $i => $week) {
$row[] = array(
'data' => number_format($line->{"week{$i}"}),
'class' => array('project-usage-numbers'),
);
}
$rows[] = $row;
}
else {
$query = $query->extend('TableSort')
->orderByHeader($headers)
->extend('PagerDefault')
->limit($items_per_page);
// Add ORDER BY NULL to the count query, overriding MySQL’s implicit GROUP
// BY ordering. This avoids a filesort.
$query->setCountQuery($count_query = $query->getCountQuery());
$count_query->getTables()['subquery']['table']->orderBy('NULL');
$result = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
$number = pager_find_page() * $items_per_page + 1;
$rows = [];
$projects = node_load_multiple(array_column($result, 'nid'));
foreach ($result as $line) {
$machine_name = field_get_items('node', $projects[$line['nid']], 'field_project_machine_name');
$row = [
['data' => $number++],
['data' => l($line['title'], 'project/usage/' . $machine_name[0]['value'])],
];
foreach ($weeks as $i => $week) {
$row[] = [
'data' => number_format($line["week{$i}"]),
'class' => ['project-usage-numbers'],
];
}
// Cache the completed page.
cache_set($cid, $rows, 'cache_project_usage', project_usage_cache_time());
// Cache number of projects.
global $pager_total_items;
cache_set('overview:total', reset($pager_total_items), 'cache_project_usage', project_usage_cache_time());
$rows[] = $row;
}
// Cache the completed page.
cache_set($cid, $rows, 'cache_project_usage', project_usage_cache_time());
// Cache number of projects.
cache_set('overview:total', $GLOBALS['pager_total_items'][0], 'cache_project_usage', project_usage_cache_time());
}
return array(
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment