Fix incorrect handling of auto-generated COUNT(*) queries when there are GROUP BY or DISTINCT clauses

This commit is contained in:
Kijin Sung 2021-01-07 00:55:43 +09:00
parent c80a80f986
commit 3f766a937c
2 changed files with 30 additions and 15 deletions

View file

@ -437,6 +437,7 @@ class DB
// Compose the output object. // Compose the output object.
$output = new \BaseObject; $output = new \BaseObject;
$output->add('_count', $query_string);
$output->total_count = $total_count; $output->total_count = $total_count;
$output->total_page = $total_page; $output->total_page = $total_page;
$output->page = $page; $output->page = $page;

View file

@ -115,27 +115,16 @@ class Query extends VariableBase
*/ */
protected function _getSelectQueryString(bool $count_only = false): string protected function _getSelectQueryString(bool $count_only = false): string
{ {
// Initialize the query string.
$result = 'SELECT ';
if ($this->select_distinct)
{
$result .= 'DISTINCT ';
}
// Compose the column list. // Compose the column list.
$columns = array(); if ($this->_column_list)
if ($count_only)
{ {
$result .= 'COUNT(*) AS `count`'; $column_list = implode(', ', array_map(function($str) {
}
elseif ($this->_column_list)
{
$result .= implode(', ', array_map(function($str) {
return self::quoteName($str); return self::quoteName($str);
}, $this->_column_list)); }, $this->_column_list));
} }
else else
{ {
$columns = array();
foreach ($this->columns as $column) foreach ($this->columns as $column)
{ {
if ($column instanceof self) if ($column instanceof self)
@ -156,7 +145,26 @@ class Query extends VariableBase
$columns[] = self::quoteName($column->name) . ($column->alias ? (' AS ' . self::quoteName($column->alias)) : ''); $columns[] = self::quoteName($column->name) . ($column->alias ? (' AS ' . self::quoteName($column->alias)) : '');
} }
} }
$result .= implode(', ', $columns); $column_list = implode(', ', $columns);
}
// Replace the column list if this is a count-only query.
if ($count_only)
{
$count_wrap = ($this->groupby || $this->select_distinct || preg_match('/\bDISTINCT\b/i', $column_list));
if ($count_wrap && ($column_list === '*' || preg_match('/\\.\\*/', $column_list)))
{
$result = 'SELECT 1';
}
else
{
$result = 'SELECT COUNT(*) AS `count`';
}
}
else
{
$count_wrap = false;
$result = 'SELECT ' . ($this->select_distinct ? 'DISTINCT ' : '') . $column_list;
} }
// Compose the FROM clause. // Compose the FROM clause.
@ -225,6 +233,12 @@ class Query extends VariableBase
$result .= ' LIMIT ' . $this->_arrangeLimitOffset($this->navigation); $result .= ' LIMIT ' . $this->_arrangeLimitOffset($this->navigation);
} }
// Wrap in a subquery if necesary.
if ($count_wrap)
{
$result = 'SELECT COUNT(*) AS `count` FROM (' . $result . ') AS `subquery`';
}
// Return the final query string. // Return the final query string.
return $result; return $result;
} }