W jednej z moich poprzednich prac zrobiłem coś podobnego:otrzymałem zapytanie (nie sql, ale całkiem podobne) i przetłumaczyłem je na zapytanie mongo za pomocą antlr.
Nie mam kodu do udostępnienia, ale mogę podzielić się swoimi przemyśleniami:
-
Mongo nie jest zgodny z SQL, więc nie możesz po prostu wziąć gramatyki sql. A co z JOIN i całą algebrą relacyjną? A co z agregacjami, które są dość trudne w mongo z ich strukturą agregacji? W przeciwnym kierunku, jak generujesz SQL, który jest tłumaczony na klauzulę "exists" w mongo. Jest wiele takich rzeczy, niektóre są małe, inne ogromne, ale w końcu musisz mówić o jakimś podzbiorze sql, o jakimś DSL, który może być używany jako język zapytań i wygląda "jak" sql, ponieważ ludzie są przyzwyczajeni do SQL.
-
Mając to na uwadze, powinieneś stworzyć własną gramatykę, a Antlr wygeneruje dla Ciebie leksykę/parser. Otrzymasz również za pewnik kontrolę składni zapytania w Runtime. Antlr nie będzie w stanie przeanalizować zapytania, jeśli nie jest ono w prawidłowym formacie, oczywiście jakaś reguła gramatyczna zawiedzie. To kolejny powód, aby nie brać SQL „tak jak jest”.
-
Do tej pory tak dobrze, że stworzyłeś własnego słuchacza / gościa. W moim przypadku zdecydowałem się na utworzenie reprezentacji obiektu zapytania ze stanem wewnętrznym i wszystkim. Więc zapytanie
Select id,name
from employee
where age > 30
and department = 'IT'
limit 200
Został przetłumaczony na obiekty typu:
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
}
W przypadku tego konkretnego zapytania wygląda to mniej więcej tak:
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));
Następnie możliwe jest dokonanie pewnych optymalizacji w zapytaniu (takich jak osadzanie klauzul where, jeśli potrzebujesz, lub na przykład manipulowanie częścią „For”, jeśli pracujesz w środowisku wielu dzierżawców i masz różne kolekcje dla różnych dzierżawców).
Przecież można przejść do wzorca projektowego "interpreter" i rekurencyjnie parsować obiekty zapytania i "przetłumaczyć" je na poprawne zapytanie mongo.Pamiętam, że ten krok zajął mi około 1 dnia (było to 7 lat temu z mongo 2 I zgadnij, ale jednak), biorąc pod uwagę poprawną strukturę obiektów reprezentujących zapytanie, nie powinno to być tak skomplikowane. Wspominam o tym, ponieważ wygląda na to, że jest to twój główny problem w pytaniu.