Skip to content

Consistent CompareXXXFunction behavior in PHP/SQL #808

@ohotovy

Description

@ohotovy

The issue occurs while testing (nette/tester), as when actually running the code, the comparison is using CompareXXXFunction::evaluateInDb(), which behaves as expected (produces an SQL query with WHERE statement evaluated according to SQL logic), whereas the tests work with CompareXXXFunction::evaluateInPhp() and thus produces a different results from SQL queries for A < B expressions when NULLs are involved.

Example:
"Select random records deleted in year 2025 and earlier"

| random_records

| id | deleted_at

| 1 | 2026-02-02

| 2 | 2025-12-02

| 3 | NULL

I believe appropriate (SQL-aligned) Nextras code would be:
$collection = $randomRecordsRepository->findBy(['deletedAt<' => new DateTimeImmutable::createFromFormat('Y-m-d','2026-01-01')]);, which produces arguably correct and without a doubt aligned-with-SQL-logic result (record ID 2 selected) normally, but during testing, it additionally selects the record with ID 3 (as in PHP, null < $anyDate), making e.g. a RandomRecordsControllerTest::testGetRecordsDeletedInPreviousYears() essentially invalid.

I think reasonable solution would be to provide out of the box "SqlAlignedCompareXXXFunction" classes, which override evaluateInPhp() methods in a way which automatically return false when either of their arguments is null.
One step further would be to make those default when parsing 'property<' => $value conditions, but I realise that would potentially break a lot of things in lot of peoples' codebases.

I have considered:

  • extending the CompareXXXFunction classes with my own methods, as suggested (implemented)
  • adding additional conditions and constraints for either a comparison value (>=, >), or property value (<=, <) to not be nulls, where relevant (not implemented, I don't think this is the correct approach)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions