Skip to content

Instantly share code, notes, and snippets.

@philippwiddra
Created March 22, 2016 23:12
Show Gist options
  • Save philippwiddra/2ee47ac4f8a0248c3a0e to your computer and use it in GitHub Desktop.
Save philippwiddra/2ee47ac4f8a0248c3a0e to your computer and use it in GitHub Desktop.
Some examples with Microsoft.SqlServer.TransactSql.ScriptDom and TSql generation and parsing
using Microsoft.SqlServer.TransactSql.ScriptDom;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TransactSqlScriptDomTest
{
class Program
{
static void Main(string[] args)
{
var sql = @"select firstname, lastname FROM persons as p;
SELECT id, name FROM companies;
select s.test from (select 'hello' as test) as s;";
TSqlParser parser = new TSql120Parser(true);
IList<ParseError> parseErrors;
TSqlFragment sqlFragment = parser.Parse(new StringReader(sql), out parseErrors);
if (parseErrors.Count > 0) Console.WriteLine("Errors:");
parseErrors.Select(e => e.Message.Indent(2)).ToList().ForEach(Console.WriteLine);
OwnVisitor visitor = new OwnVisitor();
sqlFragment.Accept(visitor);
Console.WriteLine("Done.");
Console.ReadKey();
}
}
class OwnVisitor : TSqlFragmentVisitor
{
public override void ExplicitVisit(SelectStatement node)
{
QuerySpecification querySpecification = node.QueryExpression as QuerySpecification;
FromClause fromClause = querySpecification.FromClause;
// There could be more than one TableReference!
// TableReference is not sure to be a NamedTableReference, could be as example a QueryDerivedTable
NamedTableReference namedTableReference = fromClause.TableReferences[0] as NamedTableReference;
TableReferenceWithAlias tableReferenceWithAlias = fromClause.TableReferences[0] as TableReferenceWithAlias;
string baseIdentifier = namedTableReference?.SchemaObject.BaseIdentifier?.Value;
string schemaIdentifier = namedTableReference?.SchemaObject.SchemaIdentifier?.Value;
string databaseIdentifier = namedTableReference?.SchemaObject.DatabaseIdentifier?.Value;
string serverIdentifier = namedTableReference?.SchemaObject.ServerIdentifier?.Value;
string alias = tableReferenceWithAlias.Alias?.Value;
Console.WriteLine("From:");
Console.WriteLine($" {"Server:",-10} {serverIdentifier}");
Console.WriteLine($" {"Database:",-10} {databaseIdentifier}");
Console.WriteLine($" {"Schema:",-10} {schemaIdentifier}");
Console.WriteLine($" {"Table:",-10} {baseIdentifier}");
Console.WriteLine($" {"Alias:",-10} {alias}");
// Example of changing the alias:
//(fromClause.TableReferences[0] as NamedTableReference).Alias = new Identifier() { Value = baseIdentifier[0].ToString() };
Console.WriteLine("Statement:");
Console.WriteLine(node.ToSqlString().Indent(2));
Console.WriteLine("¯".Multiply(40));
base.ExplicitVisit(node);
}
}
public static class TSqlDomHelpers
{
public static string ToSourceSqlString(this TSqlFragment fragment)
{
StringBuilder sqlText = new StringBuilder();
for (int i = fragment.FirstTokenIndex; i <= fragment.LastTokenIndex; i++)
{
sqlText.Append(fragment.ScriptTokenStream[i].Text);
}
return sqlText.ToString();
}
public static string ToSqlString(this TSqlFragment fragment)
{
SqlScriptGenerator generator = new Sql120ScriptGenerator();
string sql;
generator.GenerateScript(fragment, out sql);
return sql;
}
}
public static class StringHelpers
{
public static string Indent(this string Source, int NumberOfSpaces)
{
string indent = new string (' ', NumberOfSpaces);
return indent + Source.Replace("\n", "\n" + indent);
}
public static string Multiply(this string Source, int Multiplier)
{
StringBuilder stringBuilder = new StringBuilder(Multiplier * Source.Length);
for (int i = 0; i < Multiplier; i++)
{
stringBuilder.Append(Source);
}
return stringBuilder.ToString();
}
}
}
@vitalijroscinski
Copy link

Perfect example.
Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment