rbock / sqlpp11

A type safe SQL template library for C++
BSD 2-Clause "Simplified" License
2.47k stars 341 forks source link

[feature request] dynamic_where() to support freely building logical expressions. #604

Open margaretselzer opened 1 month ago

margaretselzer commented 1 month ago

Right now dynamic_where() only supports adding conditions in a AND relationship. E.g. according to the example

   auto s = dynamic_select(db, all_of(foo)).from(foo).dynamic_where();
   s.where.add(foo.id == 1);
   s.where.add(foo.name == "txt");

will produce the where-clause of WHERE (foo.id = 1) AND (foo.name = 'txt') without the possibility to use for example the OR operator or group sub-expressions.

A more flexible where-clause builder capability is needed so that more complex logical expressions could be dynamically built.

E.g.:

s.where.add(condition_begin);    // adds opening bracket "("
s.where.add(foo.id == 1);    // adds "(foo.id = 1)"
if (someCondition) {
  s.where.add(operator_and);    // adds "AND"
  s.where.add(foo.pos == 133);    // adds "(foo.pos = 13)"
}
s.where.add(condition_end);    // adds closing bracket ")"
if (someOtherCondition) {
  s.where.add(operator_or);    // adds "OR"
  s.where.add(foo.name == "yay");    // adds "(foo.name = 'yay')"
}

If all conditions are met, the above should yield: WHERE ((foo.id = 1) AND (foo.pos = 133)) OR (foo.name = 'yay').

My real-life need is that I have to select from a table rows where I have a match on label AND a position but the number of these label-position pairs is dynamically changing, In some cases I have just one pair, in some cases I have several and I need to return all matching rows. With the current dynamic_where it is not possible as I need an OR between all my (label = "labelX" AND pos = Y) sub-expressions.

rbock commented 1 month ago

This is in the works already. The optional-no-dynamic branch provides a much more flexible way of composing conditions dynamically.

Your example would look like this:

where((foo.id == 1 and dynamic(someCondition, foo.pos == 133)) or dynamic(someOtherCondition, foo.name == "yay"))
margaretselzer commented 1 month ago

Looks really good. :-)

It's only the branch name that is a bit curious for a branch that implements the function dynamic() :)

rbock commented 1 month ago

Thanks for the feedback, and yes, I know...

The name was about removing the old-style dynamic. But then it developed its own dynamic :-)