I have application with multiple forms where database data is listed in DBGrids.
When I want to filter certain database data by some criteria, I usually put some controls on form (TEdit, TComboBox, TDateEdit, ...) where user can input or choose data to be filtered upon, make OnChange or similar events, change SQL queries according to entered data, ...
It works but it is labour intensive to add each new field to be filtered, hard to maintain and still rather limited for filtering.
I am working on a solution to use same code across my application: I provide fields which are allowed to be filtered for some DBGrid, let user input filtering data and create SQL code to be put below 'where' and 'having' clauses in SQL.
I've solved this and I would like to give users considerably more flexibilty to filter data.
Now I mainly let them type filter criteria with only a couple possibilites: filter exact word, date or amount (resulting SQL like: where somefield = 'John Doe'; or: where somedate = '2022-04-09'), filter words including some text (resulting SQL like: where somefield like '%John%') or some range (resulting SQL like: somedate between '2022-03-01' and '2022-03-31').
I would like to allow entering expressions to be filtered upon and then convert entered expression into SQL.
This is where I would like advice in which direction or how to proceed.
Expressions I had in mind would look like this (all entered data in SQL would be passed as parameters, but I didn't want to complicate it here):
Entered criteria | Description | Resulting SQL |
John Doe | Field contains exact string | somefield = 'John Doe' |
*John* | field contains entered string | somefield like '%John%' |
120 | Field containing exact number | somefield = 120 |
120..160 | Interval between 120 and 160 | somefield between 120 and 160 |
<>100 | Field not equal to entered value (less than, greater that also should work) | somefield <> 100 |
<100&>20 | And operater | somefield < 100 and somefield > 20 |
%John%|%Paul%|%Mary% | Or operater | (somefield like '%John%' or somefield like '%Paul%' or somefield like '%Mary%') |
100|(>30&<50) | Use of parentheses | ((somefield = 100) or (somefield > 30 and somefield < 50)) |
'a*' | Single quote filters exact expression so special characters could also be searched | somefield = 'a*' |
'' | Two single quotes enable search of empty expressions | somefield = '' |
12|1103|210321 | Date fields expansion: if one or two digits is entered it refers to current month, if four digits are entered it refers to current year | (somedate = '2022-04-12' or somedate = '2022-03-11' or somedate = '2021-03-21') |
So, what would be the way to parse this expressions so I can build SQL expressions the way I want to?