[Memcached_DataObject] Check if it is possible to sort efficiently

This commit is contained in:
Alexei Sorokin 2020-06-27 11:22:19 +03:00
parent 1db6943702
commit edc7159ef6
1 changed files with 42 additions and 20 deletions

View File

@ -87,7 +87,7 @@ class Memcached_DataObject extends Safe_DataObject
} }
if ($skipNulls) { if ($skipNulls) {
foreach ($keyVals as $key=>$val) { foreach ($keyVals as $key => $val) {
if (is_null($val)) { if (is_null($val)) {
unset($keyVals[$key]); unset($keyVals[$key]);
} }
@ -97,30 +97,52 @@ class Memcached_DataObject extends Safe_DataObject
$obj->whereAddIn($keyCol, $keyVals, $colType); $obj->whereAddIn($keyCol, $keyVals, $colType);
// Since we're inputting straight to a query: format and escape // Since we're inputting straight to a query: format and escape
foreach ($keyVals as $key=>$val) { foreach ($keyVals as $key => $val) {
settype($val, $colType); settype($val, $colType);
$keyVals[$key] = $obj->escape($val); $keyVals[$key] = $obj->escape($val);
} }
switch (common_config('db', 'type')) { // Check if values are ordered, makes sorting in SQL easier
case 'pgsql': $prev_val = reset($keyVals);
// "position" will make sure we keep the desired order $order_asc = $order_desc = true;
$obj->orderBy(sprintf( foreach ($keyVals as $val) {
"position(',' || CAST(%s AS text) || ',' IN ',%s,')", if ($val < $prev_val) {
$keyCol, $order_asc = false;
implode(',', $keyVals) }
)); if ($val > $prev_val) {
$order_desc = false;
}
if ($order_asc === false && $order_desc === false) {
break; break;
case 'mysql': }
// "find_in_set" will make sure we keep the desired order $prev_val = $val;
$obj->orderBy(sprintf( }
"find_in_set(%s, '%s')",
$keyCol, if ($order_asc) {
implode(',', $keyVals) $obj->orderBy($keyCol);
)); } elseif ($order_desc) {
break; $obj->orderBy("{$keyCol} DESC");
default: } else {
throw new ServerException('Unknown DB type selected.'); 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(); $obj->find();