2015-12-05 20 views

回答

4

我做了一些研究,发现我可以使用反射来生成解析的信息xml文件,使用SqlScript.WriteXml。 这里是示例代码,我不知道是否有更好的方法。

var rst = Parser.Parse(File.ReadAllText(@"*.sql")); 
var fieldInfo = rst.GetType().GetField("sqlScript", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField); 
var script = fieldInfo.GetValue(rst); 
var writer = XmlWriter.Create("*.xml"); 
script.GetType().InvokeMember("WriteXml", BindingFlags.NonPublic| BindingFlags.Instance | BindingFlags.InvokeMethod 
    , null, script, new object[] { writer }); 
writer.Close(); 
0

我很兴奋,你找到了AST在所有!直接使用它需要使用动态变量来访问内部Microsoft.SqlServer.Management.SqlParser.SqlCodeDom名称空间中对象的.Child集合。

与其调用WriteXml,我建议访问现有的Xml字符串属性。这节省了必须处理在XML注释中嵌套SQL注释引起的问题(在XML注释中不能有--; --变为- -)。

var rst = Parser.Parse(File.ReadAllText(@"*.sql")); 
var script = rst.GetType().GetProperty("Script", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(rst); 
var xml = script.GetType().BaseType.GetProperty("Xml").GetValue(script) as String; 

如果你真的愿意接受只是元数据标记,我发现了一个PowerShell的例子here;它的工作原理出这样的事情(包括了完整的样板工厂的元数据):

// using Microsoft.SqlServer.Management.SqlParser.Parser; 
// ... 

var sql = File.ReadAllText(@"*.sql"); 
var scanner = new Scanner(new ParseOptions()); 
int scannerState = 0; 
scanner.SetSource(sql, 0); 
var allTokens = new List<MSSQL_Token_JS>(); 
MSSQL_Token_JS curToken = null; 
do 
{ 
    curToken = MSSQL_Token_JS.GetNext(scanner, sql, ref scannerState); 
    allTokens.Add(curToken); 
} 
while (curToken.Value != Tokens.EOF); 

//... 

public class MSSQL_Token_JS 
{ 
    public readonly string SourceSQL; 
    public readonly Tokens Value; 
    public readonly string Text; 
    public readonly int ScannerState; 
    public readonly int Start; 
    public readonly int End; 
    public readonly bool IsPairMatch; 
    public readonly bool IsExecAutoParamHelp; 

    private MSSQL_Token_JS(string SourceSQL, int tokenId, int ScannerState, int Start, int End, bool IsPairMatch, bool IsExecAutoParamHelp) 
    { 
     this.SourceSQL = SourceSQL; 
     this.Value = (Tokens)tokenId; 
     if (this.Value != Tokens.EOF) 
     { 
      this.Text = SourceSQL.Substring(Start, End - Start + 1); 
     } 

     this.ScannerState = ScannerState; 
     this.Start = Start; 
     this.End = End; 
     this.IsPairMatch = IsPairMatch; 
     this.IsExecAutoParamHelp = IsExecAutoParamHelp; 
    } 

    public static MSSQL_Token_JS GetNext(Scanner scanner, string SourceSQL, ref int ScannerState) 
    { 
     int start, end; 
     bool isPairMatch, isExecAutoParamHelp; 
     int tokenId = scanner.GetNext(ref ScannerState, out start, out end, out isPairMatch, out isExecAutoParamHelp); 
     return new MSSQL_Token_JS(SourceSQL, tokenId, ScannerState, start, end, isPairMatch, isExecAutoParamHelp); 
    } 

    public override string ToString() 
    { 
     return String.Format("{0}:{1}", this.Value, this.Text); 
    } 
}