rikbruil / Doctrine-Specification

Doctrine Specification pattern for building queries dynamically and with re-usable classes for composition.
MIT License
50 stars 7 forks source link

Support for mathematical operations #26

Open holtkamp opened 7 years ago

holtkamp commented 7 years ago

It seems that currently mathematical 'operations' are not possible, for example:

$specification = new Specification([
    new Equals(new Sum('entityPropertyX', 'entityPropertyY'), 10),
]);

Is this 'on purpose' / would this be even possible? Or just not developed yet? I might be able to contribute here 😇

rikbruil commented 7 years ago

It's definately not on purpose, I think It might be possible if DQL itself supports these kinds of things (not sure about this, since I havent used vanilla DQL much lately).

So my answer would be: it's not developed yet ;)

holtkamp commented 7 years ago

Ok, thanks for the answer 😄 . When trying to come up with an approach for this, I realized it can become quite complex, since the elements of the expressions can be expressions themselves as well...

I currently have quite a nice/exotic condition in SQL to ensure that a date is between a "from" and an "end" date while:

So "01-10" should be considered between "01-09" and "01-03". This requires multiple mathematical operations:

SELECT 
  MOD(DAYOFYEAR('2017-10-01') - DAYOFYEAR('2017-09-01') + 365, 365) +
  MOD(DAYOFYEAR('2017-03-01') - DAYOFYEAR('2017-10-01') + 365, 365) <= 365;

Note that next year, in 2018, this will still work: the date range has become year agnostic:

SELECT 
  MOD(DAYOFYEAR('2018-10-01') - DAYOFYEAR('2017-09-01') + 365, 365) +
  MOD(DAYOFYEAR('2017-03-01') - DAYOFYEAR('2018-10-01') + 365, 365) <= 365;

As a specification this might become something like:

$specification = new Specification([
    new LessThanOrEquals(
        new Sum(
            new Mod(DAYOFYEAR('2017-10-01') - DAYOFYEAR('2017-09-01') + 365, 365),
            new Mod(DAYOFYEAR('2017-03-01') - DAYOFYEAR('2017-10-01') + 365, 365),
        ),
        365
    )
]);

So in this case, what to do with the Custom DQL function DayOfYear() and the additional subtractions / additions.... As you can see, not as simple as it seems...