Changes for RC1 (#6)
- `ORDER BY` clauses support qualified fields - Restrict supported PHP versions; this will prevent inadvertent upgrades to the upcoming 8.4-compliant version Reviewed-on: #6
This commit is contained in:
parent
d067f8983f
commit
df436c9ef4
@ -17,9 +17,9 @@
|
||||
"rss": "https://git.bitbadger.solutions/bit-badger/pdo-document.rss",
|
||||
"docs": "https://bitbadger.solutions/open-source/pdo-document/"
|
||||
},
|
||||
"minimum-stability": "beta",
|
||||
"minimum-stability": "RC",
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"php": "8.2 - 8.3",
|
||||
"bit-badger/inspired-by-fsharp": "^1",
|
||||
"netresearch/jsonmapper": "^4",
|
||||
"ext-pdo": "*"
|
||||
|
26
composer.lock
generated
26
composer.lock
generated
@ -4,18 +4,18 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7f9c6e825e6f0968b2dedefec770f558",
|
||||
"content-hash": "ec1fce1531c57de8cb1300e3d1cf2a83",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bit-badger/inspired-by-fsharp",
|
||||
"version": "v1.0.0-beta2",
|
||||
"version": "v1.0.0-rc1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp",
|
||||
"reference": "fad428a4e40b606987499b17bb2d5b7d4b04502d"
|
||||
"reference": "6779b2c554cf52e2eea4bd0575ea308e4ac09570"
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.2"
|
||||
"php": "8.2 - 8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpoption/phpoption": "^1",
|
||||
@ -49,7 +49,7 @@
|
||||
"rss": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp.rss",
|
||||
"source": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp"
|
||||
},
|
||||
"time": "2024-07-29T17:58:33+00:00"
|
||||
"time": "2024-10-01T00:14:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "netresearch/jsonmapper",
|
||||
@ -166,16 +166,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.2.0",
|
||||
"version": "v5.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb"
|
||||
"reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb",
|
||||
"reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3abf7425cd284141dc5d8d14a9ee444de3345d1a",
|
||||
"reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -218,9 +218,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.2.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.3.0"
|
||||
},
|
||||
"time": "2024-09-15T16:40:33+00:00"
|
||||
"time": "2024-09-29T13:56:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -1844,12 +1844,12 @@
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "beta",
|
||||
"minimum-stability": "RC",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=8.2",
|
||||
"php": "8.2 - 8.3",
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
|
@ -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