I am trying mock sql syntax to build a simple sql like interface to a key-value storage.
The values are essentially POJOs
An example would be
select A.B.C from OBJ_POOL where A.B.X = 45 AND A.B.Y > '88' AND A.B.Z != 'abc';
OBJ_POOL is just a list of POJOs of the same class. In this example A would be the base class.
Class A
Class B
String C
Integer X
String Y
String Z
Now A.B.C is equivalent A.getB().getC()
I am using Antlr to parse the above statement to get an AST, and then hoping to use Apache BeanUtils to reflectively get/set the field names.
I wrote the grammar thats builds an AST

Now I am facing two problems
- How should the visitor be implemented for the where clause ? A.B.X = 45 implies all objects having field X as 45, how should the filtering happen is there any nice way to do this ?
- Is there any way to traverse the generated AST without cluttering the visitor code with custom logic (storage access,property getters/setters etc..)
The second problem is more worrying since there might be many things that the statement might do.
In a nutshell any suggestions/links/design-patterns to nicely parse a small subset of the sql select statment would be greatly appreciated
Thanks
You can do this much like how I demonstrated in my blog posts (and since I know you read those, I won’t go in much detail). The only difference in this case is that each of your rows of data has its own scope. An easy way to pass this scope along is by providing it as a parameter to the
eval(...)method.Below is a quick demo of how this could be implemented. Note that I quickly hacked this together based on my blog posts: not all functionality is available (see the many
TODO‘s, and there are likely (small) bugs in it as well. Use at your own risk!).Besides ANTLR v3.3, you need the following 3 files for this demo:
Select.g
SelectWalker.g
Main.java
(yes, stick all these Java classes in the same file:
Main.java)If you now generate the lexer, parser and tree walker and run the Main class:
you will see that the output for the query:
with input:
is:
And note that if the
wherestatement is omitted, the expression1 = 1is automatically inserted, causing the query:to print the following: