5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【.NET】SQL構文解析ライブラリーのTSQL Parserを使用する

Last updated at Posted at 2021-04-18

はじめに

2018年からサーバーリプレース作業(Windows Server 2008R2 → Windows Server 2016)でデータベースを Oracle 11g から PostgreSQL 9.6 に移行作業をしました。

PostgreSQL 9.6 のサポート終了期限が 2021年11月となっているため、PostgreSQL 12 に移行する準備を進めています。
最新のPostgreSQL 13 にしないのは、現時点(2021/04/18)で某N社のサポートがPostgreSQL 12 までだからです。

バージョン 初期リリース日 サポート終了期限
13 2020年09月 2025年11月
12 2019年10月 2024年11月
11 2018年10月 2023年11月
10 2017年10月 2022年11月
9.6 2016年09月 2021年11月

SQLの構文解析

20近くの既存アプリケーションのSQLを抜き出して、PostgreSQL 9.6とPostgreSQL 12で性能検証をする必要があります。1000近くのSQLがあるため、プログラムを組んで自動で性能検証をしたいと考えました。

自動でやるためには、登録・更新・削除するデータをDB上から抜き出し、該当のSQLに抽出条件や登録・更新データのパラメーターとして当てはめて実行したいのです。

当初は正規表現を多様してSQLを解析しようと考えていたのですが、他言語でSQL文を構文解析するという記事を見つけて、それならC#版でも似たようなのがあるだろうと、NuGetで見つけたのが「TSQL Parser」になります。

.NET Fiddleの紹介

オンライン上でC#のコードを簡単に試せる「.NET Fiddle」を初めて使用してみました。
他のC#オンラインエディタと違って、NuGet Packageを指定することで「TSQL.Parser」を使用できます。

ソースコード

using System;
using TSQL;
using TSQL.Statements;
using TSQL.Tokens;
using System.Collections.Generic;

namespace TSQLParserExample
{
	public class ParseRule 
	{
		public string Field {get;set;}
		public string Operator {get;set;}
		public string FieldValue {get;set;}
		public string SearchOperator { get; set; }
	}
	public class Program
	{
		public static void Main(string[] args)
		{
			TSQLSelectStatement select = TSQLStatementReader.ParseStatements(@"
SELECT id, name
FROM hoge h
WHERE h.id   = @id AND h.name = '@name'
				")[0] as TSQLSelectStatement;
			
			List<ParseRule> rules = new List<ParseRule>();
			
			
			if (select.Where != null)
			{
				Console.WriteLine("WHERE:");
				ParseRule ruleValue = new ParseRule();
				foreach (TSQLToken token in select.Where.Tokens)
				{
					string tokenType = token.Type.ToString();
					string tokenText = token.Text;
					
					switch(tokenType)
					{
						case "Keyword":
							if(string.IsNullOrEmpty(ruleValue.SearchOperator))
							{
								ruleValue.SearchOperator = tokenText;
							}
							else 
							{
								ruleValue.Operator = tokenText;
							}
							break;
						case "Identifier":
							ruleValue.Field = tokenText;
							break;
						case "Variable":
						case "StringLiteral":
						case "NumericLiteral":
							ruleValue.FieldValue = tokenText;
							if(!string.IsNullOrEmpty(ruleValue.SearchOperator) && ruleValue.SearchOperator.Equals("WHERE"))
							{
								ruleValue.SearchOperator = "AND";
							}
							rules.Add(ruleValue);
							ruleValue = new ParseRule();
							break;
						default:
							break;
					}
				}
				
				for(var i = 0; i < rules.Count; i++) 
				{
					var rule1 = rules[i];
					Console.WriteLine("\t Field: " + rule1.Field + "\t Operator: " + rule1.Operator + " \t SearchOperator: " + rule1.SearchOperator + "\t Value: " + rule1.FieldValue);
				}
			}
		}
	}
}

結果

ちなみにまだ研究中です。
PostgreSQLのNpgsqlのプレースホルダーは「: (コロン)」なのですが、TSQL Parserで変数として認識させるなら「@」に置き換えるとか必要かも知れません。

WHERE:
     Field: id     Operator:       SearchOperator: AND     Value: @id
     Field: name     Operator:       SearchOperator: AND     Value: '@name'

最後に

実は開発はこれからなので、何か気付いたことがあれば追記していきます。

【2022/08/08追記】
応用編を書きました。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?