2015-12-05 17 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); 
    } 
}