why
February 19, 2020, 12:08pm
1
Hello,
I’m a bit stuck trying to figure out how to dynamically combine dynamic query fragments.
Let’s say I have four dynamic query fragments:
dynamic_1 = ...
dynamic_2 = ...
dynamic_3 = ...
dynamic_4 = ...
I now need to combine them together according to a user-supplied “and/or” custom logic. One example custom logic could look like this (users can use “and”, “or”, as well as parentheses):
user_logic = "(1 and 2) or (3 and 4)"
Out of this, I would need to dynamically build the following:
...where: (^dynamic_1 and ^dynamic_2) or (^dynamic_3 and ^dynamic_4)
Any ideas for how to go about this?
Thank you.
fuelen
February 19, 2020, 12:55pm
2
You’ll need a parser for user expressions.
Read more here Writing a boolean expression parser in Elixir using NimbleParsec • Stefan Lapers how to write a parser. Actually, this article contains an example in EBNF format, just adjust it to your needs. You can use GitHub - princemaple/abnf_parsec: ABNF in, parser out · GitHub to generate code from the notation, but keep in mind that EBNF!=ABNF. This is the first step. The second one is to compile output from parser to your dynamic queries.
why
February 19, 2020, 1:15pm
3
Thank you @fuelen , will look at the links you sent now
why
February 19, 2020, 3:17pm
4
I think the second step is where my biggest problem is, even if I get the parsed output. How do I get something like a parsed “or” (for example) into a dynamic query?
fuelen
February 19, 2020, 6:23pm
5
Could you post an example of parsed output and dynamic queries?
why
February 20, 2020, 9:29am
6
Thank you for replying again, @fuelen
I will get back to this, just need to do some more thinking around this.
I think I may have found a solution for how to do user “and/or” logic here (even allowing for parentheses in the user logic): https://medium.com/@fmcgeough_49791/elixir-and-dynamic-ecto-queries-2fd9470edd68 .
The Enum.reduce approach in the do_build_query function there illustrates the second step I was confused about.
Anyway, will think some more on this first, and come back if stuck again