I ett av mina tidigare jobb gjorde jag något liknande:fick en fråga (inte en sql, men ganska lik) och översatte den till mongo-fråga med antlr.
Jag har ingen kod att dela, men jag kan dela mina tankar:
-
Mongo är inte SQL-kompatibel, så du kan inte bara ta en sql-grammatik. Hur är det med JOINs och all relationalgebra? Hur är det med aggregationer som är ganska knepiga i mongo med sitt aggregeringsramverk? I motsatt riktning, hur genererar du SQL som översätts till "exists"-klausul på mongo. Det finns många sådana här saker, vissa är små, vissa är enorma, men slutsatsen måste du prata om någon form av delmängd av sql, någon DSL som är tillåten att användas som frågespråk och ser ut som en sql eftersom människor är vana vid SQL.
-
Med det i åtanke bör du skapa din egen grammatik och Antlr genererar en lexer/parser åt dig. Du får också för givet en syntaxkontroll av frågan i Runtime. Antlr kommer inte att kunna analysera frågan om den inte är i ett korrekt format så klart, någon grammatikregel kommer att misslyckas. Detta är en annan anledning till att inte ta SQL "som den är".
-
Så långt har det gått bra, du har skapat din egen lyssnare/besökare. I mitt fall har jag valt att skapa en objektrepresentation av frågan med internt tillstånd och allt. Så frågan
Select id,name
from employee
where age > 30
and department = 'IT'
limit 200
Översattes till objekt av typen:
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
}
För just den här frågan är det något i stil med:
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));
Sedan är det möjligt att göra några optimeringar i frågan (som inbäddning av where-klausuler om du behöver, eller till exempel manipulera "För"-delen om du arbetar med flera hyresgäster och har olika samlingar för olika hyresgäster).
När allt kommer omkring kan du använda designmönster "tolk" och rekursivt analysera frågeobjekten och "översätta" dem till giltig mongo-fråga. Jag minns att det här steget tog mig ungefär 1 dag att utföra (det var 7 år sedan med mongo 2 I gissa, men ändå), givet den korrekta strukturen av objekt som representerar frågan, så detta borde inte vara så komplicerat. Jag tar upp det här, för det verkar som att det är ditt primära problem i frågan.