Add qualifier support for ORDER BY
This commit is contained in:
parent
d067f8983f
commit
4171040966
@ -143,6 +143,44 @@ class Query
|
||||
return "UPDATE $tableName SET data = :data WHERE " . self::whereById();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a field to an ORDER BY clause segment
|
||||
*
|
||||
* @param Field $field The field by which ordering should be implemented
|
||||
* @return string The ORDER BY fragment for the given field
|
||||
* @throws Exception If the database mode has not been set
|
||||
*/
|
||||
private static function mapToOrderBy(Field $field): string
|
||||
{
|
||||
$mode = Configuration::mode('render ORDER BY clause');
|
||||
|
||||
if (str_contains($field->fieldName, ' ')) {
|
||||
$parts = explode(' ', $field->fieldName);
|
||||
$field->fieldName = array_shift($parts);
|
||||
$direction = ' ' . implode(' ', $parts);
|
||||
} else {
|
||||
$direction = '';
|
||||
}
|
||||
|
||||
if (str_starts_with($field->fieldName, 'n:')) {
|
||||
$field->fieldName = substr($field->fieldName, 2);
|
||||
$value = match ($mode) {
|
||||
Mode::PgSQL => '(' . $field->path() . ')::numeric',
|
||||
Mode::SQLite => $field->path()
|
||||
};
|
||||
} elseif (str_starts_with($field->fieldName, 'i:')) {
|
||||
$field->fieldName = substr($field->fieldName, 2);
|
||||
$value = match ($mode) {
|
||||
Mode::PgSQL => 'LOWER(' . $field->path() . ')',
|
||||
Mode::SQLite => $field->path() . ' COLLATE NOCASE'
|
||||
};
|
||||
} else {
|
||||
$value = $field->path();
|
||||
}
|
||||
|
||||
return (empty($field->qualifier) ? '' : "$field->qualifier.") . $value . $direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an `ORDER BY` clause ('n:' treats field as number, 'i:' does case-insensitive ordering)
|
||||
*
|
||||
@ -152,36 +190,6 @@ class Query
|
||||
*/
|
||||
public static function orderBy(array $fields): string
|
||||
{
|
||||
if (empty($fields)) return "";
|
||||
|
||||
$mode = Configuration::mode('render ORDER BY clause');
|
||||
$sqlFields = array_map(function (Field $it) use ($mode) {
|
||||
if (str_contains($it->fieldName, ' ')) {
|
||||
$parts = explode(' ', $it->fieldName);
|
||||
$it->fieldName = array_shift($parts);
|
||||
$direction = ' ' . implode(' ', $parts);
|
||||
} else {
|
||||
$direction = '';
|
||||
}
|
||||
|
||||
if (str_starts_with($it->fieldName, 'n:')) {
|
||||
$it->fieldName = substr($it->fieldName, 2);
|
||||
$value = match ($mode) {
|
||||
Mode::PgSQL => '(' . $it->path() . ')::numeric',
|
||||
Mode::SQLite => $it->path()
|
||||
};
|
||||
} elseif (str_starts_with($it->fieldName, 'i:')) {
|
||||
$it->fieldName = substr($it->fieldName, 2);
|
||||
$value = match ($mode) {
|
||||
Mode::PgSQL => 'LOWER(' . $it->path() . ')',
|
||||
Mode::SQLite => $it->path() . ' COLLATE NOCASE'
|
||||
};
|
||||
} else {
|
||||
$value = $it->path();
|
||||
}
|
||||
|
||||
return $value . $direction;
|
||||
}, $fields);
|
||||
return ' ORDER BY ' . implode(', ', $sqlFields);
|
||||
return empty($fields) ? "" : ' ORDER BY ' . implode(', ', array_map(self::mapToOrderBy(...), $fields));
|
||||
}
|
||||
}
|
||||
|
@ -253,6 +253,25 @@ class QueryTest extends TestCase
|
||||
'ORDER BY not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('orderBy() succeeds with one qualified field for PostgreSQL')]
|
||||
public function testOrderBySucceedsWithOneQualifiedFieldForPostgreSQL(): void
|
||||
{
|
||||
Configuration::overrideMode(Mode::PgSQL);
|
||||
$field = Field::named('TestField');
|
||||
$field->qualifier = 'qual';
|
||||
$this->assertEquals(" ORDER BY qual.data->>'TestField'", Query::orderBy([$field]),
|
||||
'ORDER BY not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('orderBy() succeeds with one qualified field for SQLite')]
|
||||
public function testOrderBySucceedsWithOneQualifiedFieldForSQLite(): void
|
||||
{
|
||||
$field = Field::named('TestField');
|
||||
$field->qualifier = 'qual';
|
||||
$this->assertEquals(" ORDER BY qual.data->>'TestField'", Query::orderBy([$field]),
|
||||
'ORDER BY not constructed correctly');
|
||||
}
|
||||
|
||||
#[TestDox('orderBy() succeeds with multiple fields and direction for PostgreSQL')]
|
||||
public function testOrderBySucceedsWithMultipleFieldsAndDirectionForPostgreSQL(): void
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user