1 /**
2 Module that can parse a query.
3 */
4 module ezdb.query.parse;
5 
6 import ezdb.query.tree;
7 
8 import std.uni;
9 import std.range;
10 version(unittest) import fluent.asserts;
11 
12 /**
13 Splits camelcased words
14 */
15 private string[] splitCamelCasedWords(string sentence)
16 {
17     string[] words;
18     string word;
19     foreach (chr; sentence)
20     {
21         if (chr.isUpper)
22         {
23             words ~= word.toLower();
24             word = [chr];
25         }
26         else
27             word ~= chr;
28     }
29     words ~= word.toLower();
30     return words;
31 }
32 
33 @("Can split camelcased words")
34 unittest
35 {
36     const words = splitCamelCasedWords("helloWorldFooBar");
37     words.should.equal(["hello", "world", "foo", "bar"]);
38 }
39 
40 /**
41 Parses a query action.
42 */
43 private QueryAction parseQueryAction(string action)
44 {
45     switch (action)
46     {
47     case "find":
48     case "select":
49         return QueryAction.select;
50     case "remove":
51     case "delete":
52         return QueryAction.remove;
53     default:
54         assert(0, "Unsupported query action: " ~ action);
55     }
56 }
57 
58 /**
59 Parses a query filter.
60 */
61 private QueryFilter parseQueryFilter(string column)
62 {
63     QueryFilter filter;
64     filter.column = column;
65     filter.type = QueryFilterType.equal;
66     return filter;
67 }
68 
69 /**
70 Parses a query.
71 */
72 Query parseQuery(string sentences)
73 {
74     Query query;
75     const words = splitCamelCasedWords(sentences);
76     assert(words.length >= 3, "Query needs to contain at least 3 words");
77     query.action = parseQueryAction(words[0]);
78 
79     assert(words[1] == "by", "Second word of query should be 'by'");
80 
81     foreach (word; words[1..$].chunks(2))
82         query.filters ~= parseQueryFilter(word[1]);
83 
84     return query;
85 }
86 
87 @("Can parse a simple query")
88 unittest
89 {
90     const query = parseQuery("findById");
91     query.action.should.equal(QueryAction.select);
92     query.filters.length.should.equal(1);
93     query.filters[0].type.should.equal(QueryFilterType.equal);
94     query.filters[0].column.should.equal("id");
95 }