Developing a TSQL Domain Specific Language with "M" and the Microsoft Oslo SDK
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.
Page 3 of 4
This article was originally published on May 5, 2009