7

You can see here how nicely C#code statement is parse to tokens. For example, the following code:

namespace MyNamespace
{
    class MyClass
    {
        public void MyFunction(int arg1)
        {
            int var1 = arg1;
        }
    }
}

is parsed to this:

enter image description here

I want to do something like this but with T-SQL statement instead. For example, if I have the following T-SQL statement:

IIF(COALESCE([Col001], [Col002], [Col003]) > [Col004], [Col005] * [Col006] + ISNULL([Col007], [Col008]), CONCAT(SUBSTRING([Col009], 0, 3), 'sample text', [Col010]))

will give me something like this:

IIF, COALESCE, ISNULL, CONCAT, SUBSTRING    - functions 
[Col001], [Col002], ... , [Col010]          - columns 
0, 3, 'sample text'                         - variables

or in case I have:

ISNULL([Col001], [Col002], [Col003])

structure with errors:

[The isnull function requires 2 argument(s).] - error

There are not any free or paid up-to-date solutions and it seems to use the Microsoft parser is the best solution here. As I have read I need to use the Microsoft.SqlServer.Management.SqlParser.Parser namespace, but there are not any examples and I was not able to split the T-SQL statement the way I like. Also, it seems to work only with complete statements (you need SELECT clause for example, and I need to use it for code fragments only).

Can I do this using this namespace or it's better to start writing C# class for my needs instead?

gotqn
  • 42,737
  • 46
  • 157
  • 243
  • 2
    Even if you were able to use it, you thought about the fact that you can't probably "package" it together with your app, because it isn't licensed for this? – xanatos May 26 '15 at 08:07
  • @xanatos I am not sure I have understand you. I guess I am able to use this namespace if it is possible. While I was searching I have found some paid solutions for `T-SQL` parsers but they are not up-to-date (working with SQL Server 2008, and I am usingt SQL Server 2012/2014) – gotqn May 26 '15 at 08:09
  • 2
    I think xanatos makes a valid point here. I would use [ANTLR](http://www.antlr.org/) anyway, or [Irony](http://irony.codeplex.com/). – Patrick Hofman May 26 '15 at 08:16
  • There is at least another "microsoft" class for parsing TSQL: https://technet.microsoft.com/en-us/library/microsoft.sqlserver.transactsql.scriptdom.aspx Someone here http://sqlblogcasts.com/blogs/sqlandthelike/archive/2012/08/29/reporting-on-common-code-smells-a-poc.aspx wrote even a library using it – xanatos May 26 '15 at 08:50
  • ANTLR is used by ASP.NET MVC and a *lot* of other projects. Several SQL dialects are already available – Panagiotis Kanavos May 26 '15 at 09:14
  • This is not valid SQL -- you are showing Access SQL here. – Hogan Aug 05 '15 at 18:07
  • @Hogan It is 100% valid `T_SQL` statement executed in `SQL Server 2012`. Don't be mislead by the `IIF` and `COALESCE` function :-) – gotqn Aug 06 '15 at 06:02
  • COALESCE is a standard SQL function -- IIF is not. – Hogan Aug 06 '15 at 19:51
  • @Hogan [IIF is standard T-SQL function](https://msdn.microsoft.com/en-us/library/hh213574.aspx?f=255&MSPPError=-2147217396) – gotqn Aug 07 '15 at 06:02

1 Answers1

12

I had to add the reference manually in the csproj

Microsoft.SqlServer.Management.SqlParser, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91

Like

<Reference Include="Microsoft.SqlServer.Management.SqlParser, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />

A simple example:

string sql = "IIF(COALESCE([Col001], [Col002], [Col003]) > [Col004], [Col005] * [Col006] + ISNULL([Col007], [Col008]), CONCAT(SUBSTRING([Col009], 0, 3), 'sample text', [Col010]))";

var po = new ParseOptions { };
var scanner = new Scanner(po);
scanner.SetSource(sql, 0);

Tokens token;
int state = 0;
int start;
int end;
bool isPairMatch;
bool isExecAutoParamHelp;

while ((token = (Tokens)scanner.GetNext(ref state, out start, out end, out isPairMatch, out isExecAutoParamHelp)) != Tokens.EOF)
{
    string str = sql.Substring(start, end - start + 1);
    Console.WriteLine("{0}: {1}", token, str);
}

Taken from http://www.sqlservercentral.com/blogs/dave_ballantynes_blog/2012/03/13/parsing-t-sql-the-easy-way/

Taken from Parsing T-SQL – The easy way

Note that this parser recognizes a certain number of functions (like IIF, COALESCE, ...). Unrecognized functions are simply marked as TOKEN_ID, like column names.

bansi
  • 55,591
  • 6
  • 41
  • 52
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 1
    I have to admit this is a working example even thought it's not what I am looking for. I am going to try to write mine parser as the other parsers offered are too complex for my needs and the solution with the namespace above doesn't meet them too. – gotqn May 26 '15 at 10:02
  • 1
    @gotqn You have to remember that the parser you suggested isn't a parser used by the compiler, it is a parser used by the syntax highlighter... – xanatos May 26 '15 at 10:08