Skip to content

Commit dbcd00a

Browse files
committed
add numeric compare test
1 parent e3a8f55 commit dbcd00a

File tree

3 files changed

+107
-3
lines changed

3 files changed

+107
-3
lines changed

phpstan.neon.dist

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ parameters:
4040
-
4141
message: '~^Class Doctrine\\DBAL\\Platforms\\SqlitePlatform referenced with incorrect case: Doctrine\\DBAL\\Platforms\\SQLitePlatform\.$~'
4242
path: '*'
43-
count: 26
43+
count: 27
4444

4545
# TODO these rules are generated, this ignores should be fixed in the code
4646
# for src/Schema/TestCase.php

tests/Persistence/Sql/WithDb/SelectTest.php

+104
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,110 @@ public function testWhereExpression(): void
245245
], $this->q('employee')->where('retired', true)->where($this->q()->expr('{}=[] or {}=[]', ['surname', 'Williams', 'surname', 'Smith']))->getRows());
246246
}
247247

248+
/**
249+
* @dataProvider provideWhereNumericCompareCases
250+
*
251+
* @param array{string, array<mixed>} $exprLeft
252+
* @param array{string, array<mixed>} $exprRight
253+
*/
254+
public function testWhereNumericCompare(array $exprLeft, string $operator, array $exprRight, bool $expectPostgresqlTypeMismatchException = false, bool $expectMssqlTypeMismatchException = false, bool $expectSqliteWrongResult = false): void
255+
{
256+
$queryWhere = $this->q()->field($this->e('1'), 'v');
257+
if ($this->getDatabasePlatform() instanceof MySQLPlatform) {
258+
$queryWhere->table('(select 1)', 'dual'); // needed for MySQL 5.x when WHERE or HAVING is specified
259+
}
260+
$queryWhere->where($this->e(...$exprLeft), $operator, $this->e(...$exprRight));
261+
262+
$queryHaving = $this->q()->field($this->e('1'), 'v');
263+
if ($this->getDatabasePlatform() instanceof MySQLPlatform) {
264+
$queryHaving->table('(select 1)', 'dual'); // needed for MySQL 5.x when WHERE or HAVING is specified
265+
}
266+
if ($this->getDatabasePlatform() instanceof SQLitePlatform) {
267+
$queryHaving->group('v');
268+
}
269+
$queryHaving->having($this->e(...$exprLeft), $operator, $this->e(...$exprRight));
270+
271+
$queryWhere2 = $this->q()->field($this->e('1'), 'v');
272+
$queryWhere2->table($this->q()->field($this->e(...$exprLeft), 'a')->field($this->e(...$exprRight), 'b'), 't');
273+
$queryWhere2->where('a', $operator, $this->e('{}', ['b']));
274+
275+
$queryAll = $this->q()
276+
->field($queryWhere, 'where')
277+
->field($queryHaving, 'having')
278+
->field($queryWhere2, 'where2');
279+
280+
if (($expectPostgresqlTypeMismatchException && $this->getDatabasePlatform() instanceof PostgreSQLPlatform) || ($expectMssqlTypeMismatchException && $this->getDatabasePlatform() instanceof SQLServerPlatform)) {
281+
$this->expectException(ExecuteException::class);
282+
}
283+
try {
284+
$rows = $queryAll->getRows();
285+
} catch (ExecuteException $e) {
286+
if ($expectPostgresqlTypeMismatchException && $this->getDatabasePlatform() instanceof PostgreSQLPlatform && str_contains($e->getPrevious()->getMessage(), 'operator does not exist')) {
287+
// https://dbfiddle.uk/YJvvOTpR
288+
self::markTestIncomplete('PostgreSQL does not implicitly cast string for numeric comparison');
289+
} elseif ($expectMssqlTypeMismatchException && $this->getDatabasePlatform() instanceof SQLServerPlatform && str_contains($e->getPrevious()->getMessage(), 'Conversion failed when converting the nvarchar value \'4.0\' to data type int')) {
290+
// https://dbfiddle.uk/YmYeklp_
291+
self::markTestIncomplete('MSSQL does not implicitly cast string with decimal point for float comparison');
292+
}
293+
294+
throw $e;
295+
}
296+
297+
self::assertSame(
298+
$expectSqliteWrongResult && $this->getDatabasePlatform() instanceof SQLitePlatform
299+
? [['where' => null, 'having' => null, 'where2' => null]]
300+
: [['where' => '1', 'having' => '1', 'where2' => '1']],
301+
$rows
302+
);
303+
}
304+
305+
/**
306+
* @return iterable<list<mixed>>
307+
*/
308+
public function provideWhereNumericCompareCases(): iterable
309+
{
310+
yield [['4'], '=', ['4']];
311+
yield [['0'], '=', ['0']];
312+
yield [['4'], '<', ['5']];
313+
yield [['5'], '>', ['4']];
314+
yield [['\'4\''], '=', ['\'4\'']];
315+
yield [['\'04\''], '=', ['\'04\'']];
316+
yield [['\'4\''], '!=', ['\'04\'']];
317+
yield [['\'4\''], '!=', ['\'4.0\'']];
318+
yield [['4.4'], '=', ['4.4']];
319+
yield [['0.0'], '=', ['0.0']];
320+
yield [['4.4'], '!=', ['4.3']];
321+
322+
yield [['4'], '=', ['[]', [4]]];
323+
yield [['0'], '=', ['[]', [0]]];
324+
yield [['\'4\''], '=', ['[]', ['4']]];
325+
yield [['\'04\''], '=', ['[]', ['04']]];
326+
yield [['\'4\''], '!=', ['[]', ['04']]];
327+
yield [['\'4\''], '!=', ['[]', ['4.0']]];
328+
yield [['4.4'], '=', ['[]', [4.4]], false, false, true];
329+
yield [['0.0'], '=', ['[]', [0.0]], false, false, true];
330+
yield [['4.4'], '!=', ['[]', [4.3]]];
331+
yield [['4e1'], '=', ['[]', [40.0]], false, false, true];
332+
333+
yield [['[]', [4]], '=', ['[]', [4]]];
334+
yield [['[]', ['4']], '=', ['[]', ['4']]];
335+
yield [['[]', [4.4]], '=', ['[]', [4.4]]];
336+
yield [['[]', [4.4]], '>', ['[]', [4.3]]];
337+
yield [['[]', [true]], '=', ['[]', [true]]];
338+
yield [['[]', [false]], '=', ['[]', [false]]];
339+
340+
yield [['4'], '=', ['[]', ['04']], true, false, true];
341+
yield [['\'04\''], '=', ['[]', [4]], true, false, true];
342+
yield [['4'], '=', ['[]', [4.0]], false, true, true];
343+
yield [['4'], '=', ['[]', ['4.0']], true, true, true];
344+
yield [['2.5'], '=', ['[]', ['02.50']], true, false, true];
345+
346+
yield [['2 + 2'], '=', ['[]', [4]]];
347+
yield [['2 + 2'], '=', ['[]', ['4']], true, false, true];
348+
yield [['2 + 2.5'], '=', ['[]', [4.5]], false, false, true];
349+
yield [['2 + 2.5'], '=', ['[]', ['4.5']], true, false, true];
350+
}
351+
248352
public function testGroupConcat(): void
249353
{
250354
$q = $this->q()

tests/Persistence/Sql/WithDb/TransactionTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Atk4\Data\Model;
88
use Atk4\Data\Persistence\Sql\Exception;
9+
use Atk4\Data\Persistence\Sql\ExecuteException;
910
use Atk4\Data\Persistence\Sql\Expression;
1011
use Atk4\Data\Persistence\Sql\Query;
1112
use Atk4\Data\Schema\TestCase;
@@ -104,8 +105,7 @@ protected function executeOneFailingInsert(): void
104105
$this->q('employee')
105106
->setMulti(['name' => 'John', 'non_existent' => 'bar'])
106107
->mode('insert')->executeStatement();
107-
} catch (Exception $e) {
108-
self::assertSame('Dsql execute error', $e->getMessage());
108+
} catch (ExecuteException $e) {
109109
self::assertInstanceOf(InvalidFieldNameException::class, $e->getPrevious());
110110

111111
throw $e;

0 commit comments

Comments
 (0)