Sto armeggiando con un'astrazione di query sull'API del database WebSQL / Phonegap e mi trovo sia attratto, sia dubbioso, a definire un'API fluente che imita l'uso della grammatica della lingua inglese naturale.
Potrebbe essere più semplice spiegarlo tramite esempi. Di seguito sono tutte le query valide nella mia grammatica e i commenti spiegano la semantica prevista:
//find user where name equals "foo" or email starts with "foo@"
find("user").where("name").equals("foo").and("email").startsWith("foo@")
//find user where name equals "foo" or "bar"
find("user").where("name").equals("foo").or("bar");
//find user where name equals "foo" or ends with "bar"
find("user").where("name").equals("foo").or().endsWith("bar");
//find user where name equals or ends with "foo"
find("user").where("name").equals().or().endsWith("foo");
//find user where name equals "foo" and email is not like "%contoso.com"
find("user").where("name").equals("foo").and("email").is().not().like("%contoso.com");
//where name is not null
find("user").where("name").is().not().null();
//find post where author is "foo" and id is in (1,2,3)
find("post").where("author").is("foo").and("id").is().in(1, 2, 3);
//find post where id is between 1 and 100
find("post").where("id").is().between(1).and(100);
Modifica in base al feedback di Quentin Pradet : inoltre, l'API dovrebbe supportare forme verbali sia plurali che singolari, quindi:
//a equals b
find("post").where("foo").equals(1);
//a and b (both) equal c
find("post").where("foo").and("bar").equal(2);
Per motivi di ipotesi, supponiamo che non abbia esaurito tutti i possibili costrutti qui. Supponiamo anche che io possa coprire la maggior parte delle frasi inglesi corrette - dopo tutto, la grammatica stessa è limitata ai verbi e alle congiunzioni definite da SQL.
Modifica per quanto riguarda il raggruppamento : una "frase" è un gruppo e la precedenza è come definita in SQL: da sinistra a destra. Più gruppi potrebbero essere espressi con più where
istruzioni:
//the conjunctive "and()" between where statements is optional
find("post")
.where("foo").and("bar").equal(2).and()
.where("baz").isLessThan(5);
Come puoi vedere, la definizione di ciascun metodo dipende dal contesto grammaticale in cui si trova. Ad esempio l'argomento "metodi di congiunzione" or()
e and()
può essere lasciato fuori, oppure fare riferimento al nome di un campo o al valore previsto.
Per me questo sembra molto intuitivo, ma vorrei che tu ascoltassi il tuo feedback: è una buona e utile API o dovrei tornare indietro a un'implementazione più diretta?
Per la cronaca: questa libreria fornirà anche un'API più convenzionale, non fluente, basata su oggetti di configurazione.
... where foo = 1 or (bar = 2 and qux = 3)
:?
where("name").equals("foo").or("bar")
come (name=="foo")or bar
. Quindi non è chiaro quando una stringa rappresenta un valore letterale e quando presenta un nome di colonna, ...