Developing a TSQL Domain Specific Language with "M" and the Microsoft Oslo SDK, Page 3
Run
Executing the parsing and generating data all starts behind the WPF Application "Run" button. The Run button code appears below.GridView view; DBMediator med = new DBMediator(); GridViewLayoutBuilder viewBuild = new GridViewLayoutBuilder(); DataSet ds = null; ListconfigList = null; MParserBuilder parser = new MParserBuilder(); MGraphGenerator graphGen = new MGraphGenerator(); MGraphIterator iterator = null; MGraphTSQLQueryVisitor visitor = new MGraphTSQLQueryVisitor(); List visitors = new List (); parser.Build(_mgFile); graphGen.Run(this._inputText.Text, parser.Parser); visitor.Graph = graphGen.Builder; visitors.Add(visitor); iterator = new MGraphIterator(graphGen.Builder, graphGen.GraphRoot, visitors); iterator.Traverse(); this.SQLCode.Text = visitor.TSQL; //Now view the data view = (GridView)this.SQLData.View; ds = med.GetDataSet(this.SQLCode.Text); configList = (new GridViewColumnConfigBuilder(ds.Tables[0].Columns)).GetColumnNames(); viewBuild.View = view; viewBuild.SetColumns(configList); this.SQLData.DataContext = ds; this.SQLData.ItemsSource = ds.Tables[0].Rows;
Classes declared at the top of the code have the following responsibilities.
- GridView handles rendering the DataSet data.
- DBMediator accepts a SQL query and returns a DataSet.
- GridViewLayoutBuilder changes the GridView to match the DataSet
- MParserBuilder builds the Oslo DynamicParser from the M code
- MGraphGenerator uses the DynamicParser to build a GraphBuilder object.
- MGraphIterator navigates the GraphBuilder object, invoking a IGraphVisitor object at each node.
- MGraphTSQLQueryVisitor is the implementation of IGraphVisitor and handles SELECT statement construction.
I'll highlight the critical parts of each class beginning with the Iterator.
Navigating a Graph -- Iterator
In my prior article I demonstrated how a developer can incorporate the M code. You can view that article here http://www.codeguru.com/columns/experts/article.php/ c16043/ . In the prior article I navigated an Oslo Data structure called GraphBuilder.GraphBuilder is generated by the Oslo classes from the text input and the MGrammar loaded in the application. GraphBuilder is a hiearchal data structure somewhat matching the shape of the MGraph-like data generated in the Tree view of Intellipad. A sample from Intellipad appears below.
Click here for larger image
Figure 3: Intellipad MGraph
To consume the data I chose to construct code following two well known software patterns, the Iterator pattern embodied in the MGraphIterator class and the Visitor pattern embodied in the IMGraphIterator interface. For a complete description of the patterns refer to the sources at the end of the article.
Also, the Iterator I built does not implement IEnumerable, so you can't utilize the C# foreeach statement with the Iterator. The Iterator name refers to the pattern not the implementation.
MGraphIterator and a class implementing IMGraphIterator work like this. As viewed above, GraphBuilder is a tree-like data structure. MGraphIterator recursively traverses the nodes on the GraphBuilder invoking the Accept function on a list of IMGraphIterator based classes. A portion of the code appears below.
public void Traverse ()
{
WalkTheNodes(_graph, _root,_visitors);
}
private void WalkTheNodes(System.Dataflow.GraphBuilder graph, object nodeOn, List<IMGRAPHVISITOR> visitors)
{
bool isNode = false;
foreach (object enumNext in graph.GetSuccessors(nodeOn))
{
isNode = graph.IsNode(enumNext);
if ((isNode)) //Skip the non-nodes
{
foreach (IMGraphVisitor visitor in visitors)
{
visitor.Accept(enumNext);
}
WalkTheNodes(graph, enumNext, visitors);//Recurse to next node
}
}
}
I envisioned making the Iterator/Visitor interaction a reusable pattern. Different M languages could produce different GraphBuilders, but I thought that every GraphBuilder would be traversed in a similar manner. So, I decided to defer GraphBuilder consumption to an implementation of an interface following the Visitor pattern.
Now I'll show how I implemented a visitor for a GraphBuilder created from my "Simple SQL" DSL.
