В една от предишните ми работи направих нещо подобно:получих заявка (не sql, но доста подобна) и я преведох на mongo заявка с antlr.
Нямам код за споделяне, но мога да споделя мислите си:
-
Mongo не е съвместим със SQL, така че не можете просто да вземете sql граматика. Какво ще кажете за JOIN и цялата релационна алгебра? Какво ще кажете за агрегациите, които са доста трудни в mongo с тяхната рамка за агрегиране? В обратната посока, как генерирате SQL, който се превежда в клауза „съществува“ в mongo. Има много неща като това, някои са малки, други са огромни, но в крайна сметка трябва да говорите за някакво подмножество на sql, някакъв DSL, който е разрешен да се използва като език за заявки и изглежда „като“ sql, защото хората са свикнали с SQL.
-
Имайки предвид това, вие трябва да създадете своя собствена граматика и Antlr ще генерира лексер/парсер за вас. Ще получите също за даденост проверка на синтаксиса на заявката в Runtime. Antlr няма да може да анализира заявката, ако не е в правилен формат, очевидно някое граматично правило ще се провали. Това е още една причина да не приемате SQL "какъвто е".
-
Дотук добре, създадохте свой собствен слушател/посетител. В моя случай избрах да създам обектно представяне на заявката с вътрешно състояние и всичко останало. Така че заявката
Select id,name
from employee
where age > 30
and department = 'IT'
limit 200
Беше преведено в обекти от тип:
class Query {
private SelectClause select;
private FromClause from;
private WhereClause where;
private Limit limit;
}
class SelectClause {
private List<String> fields;
}
...
class WhereClause {
Condition root;
}
interface Condition {
...
}
class AndCondition implements Condition { // the same for Not, Or
}
За тази конкретна заявка е нещо като:
Query q = new Query(new SelectClause(["id", "name"]), new FromClause("employee"), new WhereClause(new AndCondition(new SimpleLeafCondition("age", Operators.GT, 30), new SimpleLeafCondition("department", Operators.EQ, "IT" )), new Limit(30));
След това е възможно да направите някои оптимизации в заявката (като вграждане на клаузи where, ако имате нужда, или например манипулиране на частта „За“, ако работите в среда с множество клиенти и имате различни колекции за различни клиенти).
В края на краищата можете да отидете с шаблон на проектиране „интерпретатор“ и рекурсивно да анализирате обектите на заявката и да ги „преведете“ към валидна mongo заявка. Спомням си, че тази стъпка ми отне нещо като 1 ден, за да постигна (беше преди 7 години с mongo 2 I познайте, но все пак), като се има предвид правилната структура на обектите, представляващи заявката, така че това не трябва да е толкова сложно. Повдигам това, защото изглежда, че това е основната ви грижа във въпроса.