V jedné ze svých předchozích zakázek jsem udělal něco podobného:dostal jsem dotaz (ne sql, ale dost podobný) a přeložil ho do mongo dotazu pomocí antlr.
Nemám kód ke sdílení, ale mohu se podělit o své myšlenky:
-
Mongo není kompatibilní s SQL, takže si nemůžete vzít pouze sql gramatiku. A co JOINy a celá relační algebra? A co agregace, které jsou v mongu dost složité se svým agregačním rámcem? V opačném směru, jak vygenerujete SQL, který se přeloží do klauzule „existuje“ v mongo. Existuje mnoho takových věcí, některé jsou malé, některé jsou obrovské, ale sečteno a podtrženo, musíte mluvit o nějaké podmnožině SQL, nějaké DSL, které je povoleno používat jako dotazovací jazyk a vypadá „jako“ sql, protože lidé jsou zvyklí na SQL.
-
S ohledem na to byste si měli vytvořit svou vlastní gramatiku a Antlr vám vygeneruje lexer/analyzátor. Samozřejmostí je také kontrola syntaxe dotazu v Runtime. Antlr nebude schopen analyzovat dotaz, pokud není ve správném formátu, některé gramatické pravidlo selže. To je další důvod, proč nebrat SQL "jak je".
-
Zatím je to v pořádku, vytvořili jste si vlastního posluchače/návštěvníka. V mém případě jsem se rozhodl pro vytvoření objektové reprezentace dotazu s vnitřním stavem a vším. Takže dotaz
Select id,name
from employee
where age > 30
and department = 'IT'
limit 200
Byl přeložen na objekty 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
}
Pro tento konkrétní dotaz je to něco jako:
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));
Pak je možné v dotazu provést určité optimalizace (jako je vložení klauzulí where, pokud potřebujete, nebo například manipulace s částí „Pro“, pokud pracujete v prostředí s více nájemci a máte různé kolekce pro různé tenanty).
Koneckonců, můžete použít návrhový vzor "interpret" a rekurzivně analyzovat objekty dotazu a "přeložit" je do platného mongo dotazu. Pamatuji si, že tento krok mi zabral něco jako 1 den (bylo to před 7 lety s mongo 2 I hádejte, ale přesto), vzhledem ke správné struktuře objektů reprezentujících dotaz, by to nemělo být tak složité. Uvádím to, protože to vypadá, že je to váš hlavní zájem v otázce.