diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 9c3eab58b..f2d2999ba 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -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), diff --git a/include/api.php b/include/api.php index 9fc853340..75f8ab069 100644 --- a/include/api.php +++ b/include/api.php @@ -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']), diff --git a/include/dba.php b/include/dba.php index 62728acae..5066dcd56 100644 --- a/include/dba.php +++ b/include/dba.php @@ -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); diff --git a/include/notifier.php b/include/notifier.php index e3d7d10d6..370611b4e 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -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']), diff --git a/include/ostatus.php b/include/ostatus.php index e0b33a1a4..e0ed1df19 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -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) { diff --git a/include/photos.php b/include/photos.php index 376be05c8..e872532a4 100644 --- a/include/photos.php +++ b/include/photos.php @@ -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", diff --git a/mod/admin.php b/mod/admin.php index 2652b33c1..fb463d31c 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -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']; diff --git a/mod/message.php b/mod/message.php index 9e9669146..d3bd1558c 100644 --- a/mod/message.php +++ b/mod/message.php @@ -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 ", diff --git a/mod/photos.php b/mod/photos.php index 3acd39b2a..8e4782977 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -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), diff --git a/mod/ping.php b/mod/ping.php index b5330c7b3..ba496a70b 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -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'); diff --git a/mod/profile.php b/mod/profile.php index fbce509d2..a83cb076f 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -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 diff --git a/mod/search.php b/mod/search.php index 7d588aa4d..f274b2a87 100644 --- a/mod/search.php +++ b/mod/search.php @@ -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'])); diff --git a/mod/videos.php b/mod/videos.php index 3828b8f1f..269d53785 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -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']),