2013-02-28 12 views
13

Próbuję utworzyć metodę, która konwertuje zwykłe wyrażenie sql na obiekty C#, więc zdecydowałem się użyć Irony do parsowania instrukcji sql, a następnie zwracam instrukcję jako Action, która zawiera typ oświadczenie i wartości niego w zależności od rodzajuParsowanie instrukcji SQL z Irony

Oto mój kod nie ukończył [bo mam sfrustrowany, bo nie wiem, co wtedy zrobić]

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; 
} 

Więc pytanie brzmi: jak czy mógłbym skorzystać z Irony, aby przekonwertować ciąg znaków SQL na obiekty AC#?

Oto przykład tego, co chcę osiągnąć:

INSERT INTO Osoby VALUES (4 'Nilsen', 'Johan', 'Bakken 2', 'Stavanger')

i zmusić go przekształcić w

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

dynamicznie w zależności od tego, co metoda Przeczytałem z rachunku.

Mam nadzieję, że dobrze wytłumaczyłem mój pomysł, dzięki czemu możesz mi pomóc, a jeśli coś jest niejasne, powiedz mi, a spróbuję to wyjaśnić.

+5

Zgaduję, punktem wyjścia powinno być uzyskanie odpowiedniego gramatykę SQL i przekształcenie go do gramatyki Format Irony można zrozumieć. To nie jest łatwe. Masz dużo pracy, która nie jest dla ludzi sfrustrowanych. Ale * można * to zrobić. –

+0

Mam już SQLGrammar, ale problem jest parsowanie każdego oświadczenia, wstawiania, aktualizacji, tworzenia ... następnie zwracanie jego zawartości [do wykorzystania w języku C# w innych celach] –

+0

Czy Twoje pytanie dotyczy bardziej Irony do analizowania swoich instrukcji SQL lub więcej do wykonywania konwersji na podstawie wyników analizy parsowania? Czy jesteś zadowolony z AST, że wracasz z Irony? Czy możesz pokazać niektóre z odpowiednich gramatyk SQL, z których korzystasz? –

Odpowiedz

1

Jeśli nie robisz tego jako zabawnego ćwiczenia, polecam użycie Linq do SQL, aby wygenerować klasy pośrednie lub Entity Framework jako małpę kodu Drunken wspomnianą w komentarzach.

Oto dobry artykuł możesz zacząć: Generating EF code from existing DB

1

starałem się analizować SQL z ironią, jak również. Zrezygnowałem ponieważ parser próbka SQL w Irony nie obsługiwać: CTE, porządku według numeru kolumny połowa specjalne instrukcje jak

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

Chociaż ja świetnie się czas nauki o Ironia, ja nie mam kodowanie kotletów w celu prawidłowego wdrożenia wszystkich wyżej wymienionych części.

Skończyło się na tym, że korzystałem z biblioteki parsowania SQL dostarczanej przez Microsoft. Przykładowy kod LINQPad 5 poniżej:

// 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(); 
    } 
}