2013-02-28 29 views
13

我想创建一个将常规sql语句转换为c#对象的方法,所以我决定使用反讽来解析sql语句,然后我将该语句作为一个Action返回,该Action包含声明和它取决于类型解析SQL语句的反讽

这里的值是我的非完成的代码[因为我很沮丧,因为我不知道该怎么办,然后]

private List<Action> ParseStatement(string statement) 
{ 
    var parser = new Parser(new SqlGrammar()); 
    var parsed = parser.Parse(statement); 
    var status = parsed.Status; 

    while (parsed.Status == ParseTreeStatus.Parsing) 
    { 
     Task.Yield(); 
    } 

    if (status == ParseTreeStatus.Error) 
     throw new ArgumentException("The statement cannot be parsed."); 

    ParseTreeNode parsedStmt = parsed.Root.ChildNodes[0]; 

    switch (parsedStmt.Term.Name) 
    { 
     case "insertStmt": 
      var table = parsedStmt.ChildNodes.Find(x => x.Term.Name == "Id").ChildNodes[0].Token.ValueString; 
      var valuesCount = 
       parsedStmt.ChildNodes.Find(x => x.Term.Name == "insertData").ChildNodes.Find(
        x => x.Term.Name == "exprList").ChildNodes.Count; 
      var values = parsedStmt.ChildNodes.Find(x => x.Term.Name == "insertData").ChildNodes.Find(
        x => x.Term.Name == "exprList").ChildNodes; 
      foreach (var value in values) 
      { 
       string type = value.Token.Terminal.Name; 
      } 
      break; 
    } 

    return null; 
} 

private Type ParseType(string type) 
{ 
    switch (type) 
    { 
     case "number": 
      return typeof (int); 
     case "string": 
      return typeof (string); 
    } 

    return null; 
} 

所以这里的问题是:如何我可以利用Irony将字符串SQL语句转换为ac#对象吗?

这里是什么我想要实现的一个示例:

INSERT INTO人员VALUES(4, 'Nilsen的', '约翰', '巴肯2', '斯塔万格')

并把它转化为

return new Action<string type, string table, int val1, string val2, string val3, string val4, string val5>; 

动态取决于什么方法从宣读的声明。

我希望我已经很好地解释了我的想法,所以你可以帮助我,如果有什么不清楚的地方,请告诉我,我会尽力解释它。

+5

我猜你的出发点应该是得到一个合适的SQL语法,并将其转换为Irony可以理解的语法格式。这不是件容易的事。你需要做很多不容易受挫的人的工作。但这是可以完成的。 – 2013-02-28 01:46:28

+0

我已经有SQLGrammar,但问题是解析每个语句,插入,更新,创建...然后返回它的内容[在其他用途​​中用于C#] – 2013-02-28 01:53:02

+0

您的问题更多地涉及让Irony解析您的SQL语句,或更多来执行基于解析结果的转换?你对从反讽中获得的AST满意吗?你能展示一些你正在使用的相关SQL语法吗? – 2013-07-08 18:52:37

回答

1

如果你不这样做是一个有趣的练习,我会建议使用Linq to SQL来生成您的存根类或实体框架作为注释中提到的醉酒代码猴。

这里有一个很好的文章,让你开始:​​

1

我试图解析与反讽SQL为好。我放弃了,因为在反讽样本SQL语法分析程序不处理:热膨胀系数,排序列数,一半的特殊之类的语句

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

虽然我有一个伟大的时间来学习反讽,我没有编码排序以正确实施所有上述部分。

我结束了使用微软提供的SQL解析库。下面的LINQPad 5示例代码:

// Add a reference to 
// C:\Program Files (x86)\Microsoft SQL Server\130\SDK\Assemblies\ 
// Microsoft.SqlServer.TransactSql.ScriptDom.dll 
// 
// https://blogs.msdn.microsoft.com/gertd/2008/08/21/getting-to-the-crown-jewels/ 

public void Main() 
{ 
    var sqlFilePath = @"C:\Users\Colin\Documents\Vonigo\database-scripts\Client\Estimate\spClient_EstimateAddNew.sql"; 
    bool fQuotedIdenfifiers = false; 
    var parser = new TSql100Parser(fQuotedIdenfifiers); 

    string inputScript = File.ReadAllText(sqlFilePath); 
    IList<ParseError> errors; 
    using (StringReader sr = new StringReader(inputScript)) 
    { 
     var fragment = parser.Parse(sr, out errors); 
     fragment.Dump(); 
    } 
}