visitor pattern 으로 짠 sql parser
sql css 에서 가져왔는데....어디인지 링크를 잊어버림....잘 찾아보면 있을겁니다.
using Microsoft.SqlServer.TransactSql.ScriptDom;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
class TSqlNormalizerSingle
{
static string hashValue;
//public static string Normalize(MemoryStream input, int compatLevel, bool caseSensitive)
public static string Normalize(string input, int compatLevel, bool caseSensitive)
{
TextReader rdr = new StringReader(input);
TSqlParser parser;
SqlScriptGenerator scrgen = null;
#region a
switch (compatLevel)
{
case 80:
{
scrgen = new Sql80ScriptGenerator();
parser = new TSql80Parser(true);
break;
}
case 90:
{
scrgen = new Sql90ScriptGenerator();
parser = new TSql90Parser(true);
break;
}
case 100:
{
scrgen = new Sql100ScriptGenerator();
parser = new TSql100Parser(true);
break;
}
case 110:
{
scrgen = new Sql110ScriptGenerator();
parser = new TSql110Parser(true);
break;
}
default:
{
return "Invalid compatibility level specified; exiting.";
}
}
#endregion a
IList<ParseError> errs;
TSqlFragment frag = parser.Parse(rdr, out errs);
foreach (ParseError err in errs)
{
//Console.WriteLine(err.Message);
if (err.Message.Length > 1)
return "query_hash_error";
}
foreach (var batch in (frag as TSqlScript).Batches)
{
myvisitor visit = new myvisitor();
StringBuilder origscript = new StringBuilder();
for (int tokIdx = batch.FirstTokenIndex; tokIdx <= batch.LastTokenIndex; tokIdx++)
{
origscript.Append(batch.ScriptTokenStream[tokIdx].Text);
}
batch.Accept(visit);
string script;
scrgen.GenerateScript(batch, out script);
using (var hashProvider = new SHA1CryptoServiceProvider())
{
if (caseSensitive)
{
hashValue = Convert.ToBase64String(hashProvider.ComputeHash(Encoding.Unicode.GetBytes(script)));
}
else
{
hashValue = Convert.ToBase64String(hashProvider.ComputeHash(Encoding.Unicode.GetBytes(script.ToLowerInvariant())));
}
}
}
return hashValue;
}
}