From edc7159ef673925d44e9cfa17aa03be5858fdb1d Mon Sep 17 00:00:00 2001 From: Alexei Sorokin Date: Sat, 27 Jun 2020 11:22:19 +0300 Subject: [PATCH] [Memcached_DataObject] Check if it is possible to sort efficiently --- classes/Memcached_DataObject.php | 62 +++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 2d1f7946a1..350b7659b4 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -87,7 +87,7 @@ class Memcached_DataObject extends Safe_DataObject } if ($skipNulls) { - foreach ($keyVals as $key=>$val) { + foreach ($keyVals as $key => $val) { if (is_null($val)) { unset($keyVals[$key]); } @@ -97,30 +97,52 @@ class Memcached_DataObject extends Safe_DataObject $obj->whereAddIn($keyCol, $keyVals, $colType); // Since we're inputting straight to a query: format and escape - foreach ($keyVals as $key=>$val) { + foreach ($keyVals as $key => $val) { settype($val, $colType); $keyVals[$key] = $obj->escape($val); } - switch (common_config('db', 'type')) { - case 'pgsql': - // "position" will make sure we keep the desired order - $obj->orderBy(sprintf( - "position(',' || CAST(%s AS text) || ',' IN ',%s,')", - $keyCol, - implode(',', $keyVals) - )); + // Check if values are ordered, makes sorting in SQL easier + $prev_val = reset($keyVals); + $order_asc = $order_desc = true; + foreach ($keyVals as $val) { + if ($val < $prev_val) { + $order_asc = false; + } + if ($val > $prev_val) { + $order_desc = false; + } + if ($order_asc === false && $order_desc === false) { break; - case 'mysql': - // "find_in_set" will make sure we keep the desired order - $obj->orderBy(sprintf( - "find_in_set(%s, '%s')", - $keyCol, - implode(',', $keyVals) - )); - break; - default: - throw new ServerException('Unknown DB type selected.'); + } + $prev_val = $val; + } + + if ($order_asc) { + $obj->orderBy($keyCol); + } elseif ($order_desc) { + $obj->orderBy("{$keyCol} DESC"); + } else { + switch (common_config('db', 'type')) { + case 'pgsql': + // "position" will make sure we keep the desired order + $obj->orderBy(sprintf( + "position(',' || CAST(%s AS text) || ',' IN ',%s,')", + $keyCol, + implode(',', $keyVals) + )); + break; + case 'mysql': + // "find_in_set" will make sure we keep the desired order + $obj->orderBy(sprintf( + "find_in_set(%s, '%s')", + $keyCol, + implode(',', $keyVals) + )); + break; + default: + throw new ServerException('Unknown DB type selected.'); + } } $obj->find();