Есть самодельный визуальный редактор запросов. Запрос представляет собой линейный список из условий и логических операций (три варианта:
AND,
OR и
() AND ()). У первой строчки операции нет. () AND () — это такой AND, приоритет которого ниже даже OR.
Вполне реальный запрос, придуманный «в поле».
группа = 'A'
AND хитрый параметр < 70%
OR группа = 'B'
AND хитрый параметр < 40%
OR группа = 'C'
AND хитрый параметр < 20%
() AND () поставщик = 'первый'
OR поставщик = 'второй'
Эквивалентное условие будет:
((г='A' & хп < 70%) | (г='B' & хп < 40%) | (г='C' & хп < 20%)) & (п = 'первый' | п = 'второй')
Три задачи.
1. Вот у нас этот запрос лежит в визуальном редакторе. Расставить автоматом отступы так, чтобы была понятна логика. Как-то так.
группа = 'A'
AND хитрый параметр < 70%
OR группа = 'B'
AND хитрый параметр < 40%
OR группа = 'C'
AND хитрый параметр < 20%
() AND () поставщик = 'первый'
OR поставщик = 'второй'
Пока наклёвывается алгоритм: у приоритетного AND отступ 0, у OR 1, у AND 2, у первого пункта без операции — такой же, как у второго. Остаётся только сократить отступы, если нет приоритетного AND.
2. Превратить этот линейный список в план исполнения запроса. Что-то вроде этого.
1. группа = 'A': +2, −3 // при срабатывании GOTO 2, при неудаче — GOTO 3.
2. хитрый параметр < 70%: +7, −3
3. группа = 'B': +4, −5
4. хитрый параметр < 40%: +7, −5
5. группа = 'C': +6, −FALSE // при срабатывании GOTO 6, при несрабатывании — неудача
6. хитрый параметр < 40%: +7, −FALSE
7. поставщик = 'первый': +TRUE, −8
8. поставщик = 'второй': +TRUE, −FALSE
3. А теперь, представьте себе, мы ввели такое.
группа = 'A'
AND хитрый_параметр < 70%
OR группа = 'B'
AND хитрый параметр < 40%
OR группа = 'C'
AND хитрый параметр < 20%
() AND () (дырка)
AND поставщик = 'первый'
OR поставщик = 'второй'
Считаем, что дырка представляет собой тождественное TRUE.
Как преобразовать запрос в эквивалентный, но без дырок? Вместо AND поставить наименее приоритетный из ()AND() и AND?