Merge pull request #3323 from Alkarex/ostatus-only_full_group_by

Fix MySQL bugs related to only_full_group_by
This commit is contained in:
Hypolite Petovan 2017-04-15 18:32:50 -04:00 committed by GitHub
commit d1fd797d6e
13 changed files with 71 additions and 32 deletions

View File

@ -502,7 +502,7 @@ function acl_lookup(App $a, $out_type = 'json') {
INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id` AND `group_member`.`uid` = `group`.`uid`
WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
$sql_extra
GROUP BY `group`.`name`
GROUP BY `group`.`name`, `group`.`id`
ORDER BY `group`.`name`
LIMIT %d,%d",
intval(local_user()),
@ -625,7 +625,7 @@ function acl_lookup(App $a, $out_type = 'json') {
FROM `item` WHERE `parent` = %d
AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
AND `author-link` NOT IN ('%s')
GROUP BY `author-link`
GROUP BY `author-link`, `author-avatar`, `author-name`
ORDER BY `author-name` ASC
",
intval($conv_id),

View File

@ -3064,7 +3064,7 @@ use \Friendica\Core\Config;
function api_fr_photos_list($type) {
if (api_user()===false) throw new ForbiddenException();
$r = q("select `resource-id`, max(scale) as scale, album, filename, type from photo
where uid = %d and album != 'Contact Photos' group by `resource-id`",
where uid = %d and album != 'Contact Photos' group by `resource-id`, album, filename, type",
intval(local_user())
);
$typetoext = array(
@ -3099,11 +3099,14 @@ use \Friendica\Core\Config;
$scale = (x($_REQUEST, 'scale') ? intval($_REQUEST['scale']) : false);
$scale_sql = ($scale === false ? "" : sprintf("and scale=%d",intval($scale)));
$data_sql = ($scale === false ? "" : "data, ");
$data_sql = ($scale === false ? "" : "ANY_VALUE(data) AS data,");
$r = q("select %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
`type`, `height`, `width`, `datasize`, `profile`, min(`scale`) as minscale, max(`scale`) as maxscale
from photo where `uid` = %d and `resource-id` = '%s' %s group by `resource-id`",
$r = q("select %s ANY_VALUE(`resource-id`) AS `resource-id`, ANY_VALUE(`created`) AS `created`,
ANY_VALUE(`edited`) AS `edited`, ANY_VALUE(`title`) AS `title`, ANY_VALUE(`desc`) AS `desc`,
ANY_VALUE(`album`) AS `album`, ANY_VALUE(`filename`) AS `filename`, ANY_VALUE(`type`) AS `type`,
ANY_VALUE(`height`) AS `height`, ANY_VALUE(`width`) AS `width`, ANY_VALUE(`datasize`) AS `datasize`,
ANY_VALUE(`profile`) AS `profile`, min(`scale`) as minscale, max(`scale`) as maxscale
from photo where `uid` = %d and `resource-id` = '%s' %s",
$data_sql,
intval(local_user()),
dbesc($_REQUEST['photo_id']),

View File

@ -20,6 +20,7 @@ class dba {
private $driver;
public $connected = false;
public $error = false;
private $_server_info = '';
function __construct($server, $user, $pass, $db, $install = false) {
$a = get_app();
@ -103,18 +104,20 @@ class dba {
* @return string
*/
public function server_info() {
switch ($this->driver) {
case 'pdo':
$version = $this->db->getAttribute(PDO::ATTR_SERVER_VERSION);
break;
case 'mysqli':
$version = $this->db->server_info;
break;
case 'mysql':
$version = mysql_get_server_info($this->db);
break;
if ($this->_server_info == '') {
switch ($this->driver) {
case 'pdo':
$this->_server_info = $this->db->getAttribute(PDO::ATTR_SERVER_VERSION);
break;
case 'mysqli':
$this->_server_info = $this->db->server_info;
break;
case 'mysql':
$this->_server_info = mysql_get_server_info($this->db);
break;
}
}
return $version;
return $this->_server_info;
}
/**
@ -474,6 +477,26 @@ class dba {
}
}
}
/**
* @brief Replaces ANY_VALUE() function by MIN() function,
* if the database server does not support ANY_VALUE().
*
* Considerations for Standard SQL, or MySQL with ONLY_FULL_GROUP_BY (default since 5.7.5).
* ANY_VALUE() is available from MySQL 5.7.5 https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html
* A standard fall-back is to use MIN().
*
* @param string $sql An SQL string without the values
* @return string The input SQL string modified if necessary.
*/
public function any_value_fallback($sql) {
$server_info = $this->server_info();
if (version_compare($server_info, '5.7.5', '<') ||
(stripos($server_info, 'MariaDB') !== false)) {
$sql = str_ireplace('ANY_VALUE(', 'MIN(', $sql);
}
return $sql;
}
}
function printable($s) {
@ -514,6 +537,7 @@ function q($sql) {
unset($args[0]);
if ($db && $db->connected) {
$sql = $db->any_value_fallback($sql);
$stmt = @vsprintf($sql,$args); // Disabled warnings
//logger("dba: q: $stmt", LOGGER_ALL);
if ($stmt === false)
@ -550,6 +574,7 @@ function qu($sql) {
unset($args[0]);
if ($db && $db->connected) {
$sql = $db->any_value_fallback($sql);
$stmt = @vsprintf($sql,$args); // Disabled warnings
if ($stmt === false)
logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true), LOGGER_DEBUG);

View File

@ -516,7 +516,8 @@ function notifier_run(&$argv, &$argc){
$r0 = Diaspora::relay_list();
}
$r1 = q("SELECT DISTINCT(`batch`), `id`, `name`,`network` FROM `contact` WHERE `network` = '%s'
$r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network`
FROM `contact` WHERE `network` = '%s'
AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch` ORDER BY rand()",
dbesc(NETWORK_DIASPORA),
intval($owner['uid']),

View File

@ -720,11 +720,11 @@ class ostatus {
$conversations = q("SELECT `term`.`oid`, `term`.`url`, `term`.`uid` FROM `term`
STRAIGHT_JOIN `thread` ON `thread`.`iid` = `term`.`oid` AND `thread`.`uid` = `term`.`uid`
WHERE `term`.`type` = 7 AND `term`.`term` > '%s' AND `thread`.`mention`
GROUP BY `term`.`url`, `term`.`uid` ORDER BY `term`.`term` DESC", dbesc($start));
GROUP BY `term`.`url`, `term`.`uid`, `term`.`oid`, `term`.`term` ORDER BY `term`.`term` DESC", dbesc($start));
} else {
$conversations = q("SELECT `oid`, `url`, `uid` FROM `term`
WHERE `type` = 7 AND `term` > '%s'
GROUP BY `url`, `uid` ORDER BY `term` DESC", dbesc($start));
GROUP BY `url`, `uid`, `oid`, `term` ORDER BY `term` DESC", dbesc($start));
}
foreach ($conversations AS $conversation) {

View File

@ -48,7 +48,7 @@ function photo_albums($uid, $update = false) {
if (!Config::get('system', 'no_count', false)) {
/// @todo This query needs to be renewed. It is really slow
// At this time we just store the data in the cache
$albums = qu("SELECT COUNT(DISTINCT `resource-id`) AS `total`, `album`
$albums = qu("SELECT COUNT(DISTINCT `resource-id`) AS `total`, `album`, ANY_VALUE(`created`) AS `created`
FROM `photo`
WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' $sql_extra
GROUP BY `album` ORDER BY `created` DESC",

View File

@ -290,7 +290,8 @@ function admin_page_federation(App $a) {
foreach ($platforms as $p) {
// get a total count for the platform, the name and version of the
// highest version and the protocol tpe
$c = qu('SELECT COUNT(*) AS `total`, `platform`, `network`, `version` FROM `gserver`
$c = qu('SELECT COUNT(*) AS `total`, ANY_VALUE(`platform`) AS `platform`,
ANY_VALUE(`network`) AS `network`, MAX(`version`) AS `version` FROM `gserver`
WHERE `platform` LIKE "%s" AND `last_contact` >= `last_failure`
ORDER BY `version` ASC;', $p);
$total = $total + $c[0]['total'];

View File

@ -349,7 +349,7 @@ function message_content(App $a) {
$o .= $header;
$r = q("SELECT count(*) AS `total` FROM `mail`
$r = q("SELECT count(*) AS `total` FROM `mail`, ANY_VALUE(`created`) AS `created`
WHERE `mail`.`uid` = %d GROUP BY `parent-uri` ORDER BY `created` DESC",
intval(local_user())
);
@ -528,9 +528,14 @@ function message_content(App $a) {
}
function get_messages($user, $lstart, $lend) {
//TODO: rewritte with a sub-query to get the first message of each private thread with certainty
return q("SELECT max(`mail`.`created`) AS `mailcreated`, min(`mail`.`seen`) AS `mailseen`,
`mail`.* , `contact`.`name`, `contact`.`url`, `contact`.`thumb` , `contact`.`network`,
ANY_VALUE(`mail`.`id`), ANY_VALUE(`mail`.`uid`), ANY_VALUE(`mail`.`guid`), ANY_VALUE(`mail`.`from-name`),
ANY_VALUE(`mail`.`from-photo`), ANY_VALUE(`mail`.`from-url`), ANY_VALUE(`mail`.`contact-id`),
ANY_VALUE(`mail`.`convid`), ANY_VALUE(`mail`.`title`), ANY_VALUE(`mail`.`body`), ANY_VALUE(`mail`.`seen`),
ANY_VALUE(`mail`.`reply`), ANY_VALUE(`mail`.`replied`), ANY_VALUE(`mail`.`unknown`),
ANY_VALUE(`mail`.`uri`), ANY_VALUE(`mail`.`parent-uri`), ANY_VALUE(`mail`.`created`),
ANY_VALUE(`contact`.`name`), ANY_VALUE(`contact`.`url`), ANY_VALUE(`contact`.`thumb`), ANY_VALUE(`contact`.`network`),
count( * ) as count
FROM `mail` LEFT JOIN `contact` ON `mail`.`contact-id` = `contact`.`id`
WHERE `mail`.`uid` = %d GROUP BY `parent-uri` ORDER BY `mailcreated` DESC LIMIT %d , %d ",

View File

@ -1240,7 +1240,9 @@ function photos_content(App $a) {
$order = 'DESC';
}
$r = q("SELECT `resource-id`, `id`, `filename`, type, max(`scale`) AS `scale`, `desc` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
$r = q("SELECT `resource-id`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`filename`) AS `filename`,
ANY_VALUE(`type`) AS `type`, max(`scale`) AS `scale`, ANY_VALUE(`desc`) as `desc`
FROM `photo` WHERE `uid` = %d AND `album` = '%s'
AND `scale` <= 4 $sql_extra GROUP BY `resource-id` ORDER BY `created` $order LIMIT %d , %d",
intval($owner_uid),
dbesc($album),

View File

@ -199,7 +199,7 @@ function ping_init(App $a)
$cachekey = "ping_init:".local_user();
$ev = Cache::get($cachekey);
if (is_null($ev)) {
$ev = qu("SELECT count(`event`.`id`) AS total, type, start, adjust FROM `event`
$ev = qu("SELECT type, start, adjust FROM `event`
WHERE `event`.`uid` = %d AND `start` < '%s' AND `finish` > '%s' and `ignore` = 0
ORDER BY `start` ASC ",
intval(local_user()),
@ -212,7 +212,7 @@ function ping_init(App $a)
}
if (dbm::is_result($ev)) {
$all_events = intval($ev[0]['total']);
$all_events = count($ev);
if ($all_events) {
$str_now = datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d');

View File

@ -210,7 +210,7 @@ function profile_content(App $a, $update = 0) {
if ($update) {
$r = q("SELECT distinct(parent) AS `item_id`, `item`.`network` AS `item_network`
$r = q("SELECT distinct(parent) AS `item_id`, `item`.`network` AS `item_network`, `item`.`created`
FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND

View File

@ -214,7 +214,7 @@ function search_content(App $a) {
FROM `item` %s
WHERE %s AND (`item`.`uid` = 0 OR (`item`.`uid` = %s AND NOT `item`.`global`))
$sql_extra
GROUP BY `item`.`uri` ORDER BY `item`.`id` DESC LIMIT %d , %d",
GROUP BY `item`.`uri`, `item`.`id` ORDER BY `item`.`id` DESC LIMIT %d , %d",
item_fieldlists(), item_joins(), item_condition(),
intval(local_user()),
intval($a->pager['start']), intval($a->pager['itemspage']));

View File

@ -356,7 +356,9 @@ function videos_content(App $a) {
$a->set_pager_itemspage(20);
}
$r = q("SELECT hash, `id`, `filename`, filetype FROM `attach`
$r = q("SELECT hash, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`created`) AS `created`,
ANY_VALUE(`filename`) AS `filename`, ANY_VALUE(`filetype`) as `filetype`
FROM `attach`
WHERE `uid` = %d AND filetype LIKE '%%video%%'
$sql_extra GROUP BY hash ORDER BY `created` DESC LIMIT %d , %d",
intval($a->data['user']['uid']),