T sql の parse と generator
-
Upload
oda-shinsuke -
Category
Documents
-
view
1.039 -
download
1
Transcript of T sql の parse と generator
T-SQL の Parse と Generate
2013/03/23 SQLWorld 大阪 #12SQLWorld お だ
自己紹介
織田 信亮大阪で開発者していますSQLWorld の代表です
http://d.hatena.ne.jp/odashinsuke/Twitter:@shinsukeoda
アジェンダ
Parse と Generate って?どうやるの?何に使える?使ってみた!まとめ
このセッションの注意事項
全ての機能は紹介出来ません!紹介するライブラリでは、 1000 近くの Class, 200 近くの Enum がある簡単な Parse と Generate に絞ってます。
Parse と Generate って?どうやるの?何に使える?使ってみた!まとめ
Parse と Generate
Parse ( パース )SQL 文 => 構文毎に分解したデータ構造の集まり
Generate ( ジェネレート )構文毎のデータ構造の集まり => SQL 文
クエリ
SELECT 句
列 1 列 2
FROM 句
テーブル
SELECT 列 1, 列2 FROM テーブル
Parse
クエリ
SELECT 句
列 1 列 2
FROM 句
テーブル
SELECT 列 1, 列2 FROM テーブル
Generate
Parse と Generate
Parse ( パース )SQL 文 => 構文毎に分解したデータ構造の集まり
Generate ( ジェネレート )構文毎のデータ構造の集まり => SQL 文
Parser ( パーサー )Parse してくれる便利なやつ
Generator ( ジェネレーター )Generate してくれる良いやつ
Parser と Generator
MS から .NET Framework のライブラリとして提供Microsoft.SqlServer.TransactSql.ScriptDom 名前空間
1 世代前は…Microsoft.Data.Schema.ScriptDomMicrosoft.Data.Schema.ScriptDom.Sql
SQL Server 2012 Feature Pack の 「 Transact-SQL ScriptDom 」 をインストール
SQL Server は不要
Parse と Generate って?どうやるの?何に使える?使ってみた!まとめ
インストール
Microsoft SQL Server 2012 Feature Packhttp://www.microsoft.com/ja-jp/download/details.aspx?id=29065
準備
参照の追加Microsoft.SqlServer.TransactSql.ScriptDom
Parse してみる
TSqlParser クラスParse メソッドを使う
using Microsoft.SqlServer.TransactSql.ScriptDom;using System.Collections.Generic;using System.IO;
var parser = new TSql110Parser(false);IList<ParseError> errors;TSqlFragment parsed;using (var query = new StringReader("select * from Table1")) { parsed = parser.Parse(query, out errors);}
Parse してみる ( エラー )
ParseError クラスLine, Column, Message プロパティから行、文字位置、エラー内容を取れる
if (errors.Count != 0) { foreach (var error in errors) { System.Console.WriteLine("{0} 行目 {1} 文字目 {2}", error.Line, error.Column, error.Message); }}
Generate してみる
SqlScriptGenerator クラスGenerateScript メソッドを使う
var options = new SqlScriptGeneratorOptions() { KeywordCasing = KeywordCasing.Uppercase, IncludeSemicolons = true, NewLineBeforeFromClause = true, NewLineBeforeOrderByClause = true, NewLineBeforeWhereClause = true};var generator = new Sql110ScriptGenerator(options);string generated;generator.GenerateScript(parsed, out generated);
もうちょっと細かいとこまで
Parser – バージョン毎に用意されてるTSql80Parser - SQL Server 2000 用TSql90Parser - SQL Server 2005 用TSql100Parser - SQL Server 2008 用TSql110Parser - SQL Server 2012 用
バージョンが違うとエラーになる構文も…
もうちょっと細かいとこまで
Parse 結果TSqlFragment – 基底クラスTSqlScript, TSqlBatch, TSqlStatement, SelectElement, FromClause, WhereClause, Identifier, CreateTableStatement, 等々 800 個近い継承したクラスがあるDML に限らず、 DDL や DBCC 等の全ての T-SQL に対応している「はず!」
Visitor パターンになっているので、 Visitor を実装すれば色々出来る
もうちょっと細かいとこまで
Visitorどちらかのクラスを継承し、目的の Visitor メソッドを override するTSqlFragmentVisitor
呼び出される Visitor メソッドのパラメータは継承した物も含む
TSqlConcreteFragmentVisitorVisitor メソッドのパラメータ型は厳密
もうちょっと細かいとこまで
例: SELECT で指定している項目の数を数えるhttp://msdn.microsoft.com/ja-jp/library/microsoft.sqlserver.transactsql.scriptdom.selectelement.aspx
SELECT @Id = A.Id, @Name = B.Name FROM ( SELECT * FROM Table1 WHERE Id = 1) A INNER JOIN Table2 B ON ( A.USERID = B.ID )
もうちょっと細かいとこまで
TSqlFragmentVisitorSELECT で指定している項目全ての件数を数える Visitor
public class SelectElementVisitor : TSqlFragmentVisitor { public int Count { get; set; } public override void Visit(SelectElement node) { Count++; base.Visit(node); }}
もうちょっと細かいとこまで
TSqlConcreteFragmentVisitorSELECT で指定している “ *” の件数を数える Visitor
public class SelectStarVisitor : TSqlFragmentVisitor { public int Count { get; set; } public override void Visit(SelectStarExpression node) { Count++; base.Visit(node); }}
もうちょっと細かいとこまで
カスタム Visitor を利用するvar q = @"SELECT @Id = A.Id, @Name = B.Name FROM ( SELECT * FROM Table1 WHERE Id = 1) A INNER JOIN Table2 B ON ( A.USERID = B.ID )";var f = new TSql110Parser(false) .Parse(new StringReader(q), out errors);
var v1 = new SelectElementVisitor();var v2 = new SelectStarVisitor();f.Accept(v1);f.Accept(v2);
Console.WriteLine(v1.Count); // 3Console.WriteLine(v2.Count); // 1
もうちょっと細かいとこまで
Generator – バージョン毎に用意されてるSql80ScriptGenerator - SQL Server 2000 用Sql90ScriptGenerator - SQL Server 2005 用Sql100ScriptGenerator - SQL Server 2008 用Sql110ScriptGenerator - SQL Server 2012 用
イマイチ違いが判らず…
もうちょっと細かいとこまで
TSqlFragment を組み立てて、クエリを生成する
「もうちょっと」 で済まないくらい大変!!
お勧めはしないhttp://d.hatena.ne.jp/odashinsuke/20130224/1361714459
Parse と Generate って?どうやるの?何に使える?使ってみた!まとめ
MSDN に掲載されているサンプル
チュートリアル : SQL 用のカスタムの静的コード分析規則アセンブリを作成する
http://msdn.microsoft.com/ja-jp/library/dd172127%28v=vs.100%29.aspx
Visual Studio 2008/2010 でのコード解析 で 「 WAITFOR DELAY 」 が使用されているか検出するチュートリアル
何に使えるの?
アイデア募集中!
何に使えるの?
クエリの検証構文エラーの検出コーディング規約のチェック
クエリの書式設定 / 統一クエリの部分抽出動的なクエリ生成
クエリの改造
クエリの検証
構文エラーの検出実 DB が無い環境でも SQL の構文が正しいか判定出来る注意点としてオブジェクトの存在チェックは出来ない!
SQL Server のバージョン毎に構文チェックが可能なので、移行検証時に使えるかもSQL Server の Ver UP や 他社 DB (Oracle 等 ) からの移行
クエリの検証
コーディング規約のチェック例えば…DELETE は使わない ( 論理削除 )マスタテーブル (MST_ ~ ) は inner join とか
漏れやすい項目の検証SELECT 文に ORDER BY が存在していないクエリの検出スキーマ指定漏れ定型的な条件の漏れ (DELETE_FLG = 0 とか )COLLATE 指定
クエリの書式設定 / 統一
クエリのフォーマットキーワードの大文字 / 小文字化識別子の [] 囲みインデント改行
クエリの部分抽出
サブクエリだけ抜き出すSELECT の結果カラムだけ抜き出すINSERT – SELECT から SELECT だけ抜き出す
INSERT 実行前に更新対象を確認 ( クエリ自体は 1 つで可能 )
動的なクエリ生成
クエリの改造ER => DDL (CREATE TABLE) で共通的なカラムの追加SELECT で共通的なカラムの追加COUNT(*) OVER() AS [ 全件数 ]
INSERT/UPDATE で共通的なカラムの追加更新日 / 更新者 等
Parse と Generate って?どうやるの?何に使える?使ってみた!まとめ
ScriptDom のサンプルサイト
ScriptDom Samplehttp://scriptdomsample.azurewebsites.net/クエリの書式設定 / 統一クエリの部分抽出クエリの改造
ビルド時の SQL 検証
MSBuild のタスクとして作成するプロジェクト内に存在する .sql ファイルで SELECT 文の物を対象に ORDER BY が存在しなかったらエラーとする
まとめ
T-SQL には、 MS 公式の Parser/Generator があるSQL Server 2000, 2005, 2008, 2012 の 4 バージョン面白そうではあるけど、どこで / 何に使うのかはアイデアが要るかも
参考資料
Microsoft SQL Server 2012 Feature Packhttp://www.microsoft.com/ja-jp/download/details.aspx?id=29065
Microsoft.SqlServer.TransactSql.ScriptDom 名前空間http://msdn.microsoft.com/ja-jp/library/hh215705.aspx
Visual Studio のデータベース機能の API リファレンスhttp://msdn.microsoft.com/ja-jp/library/dd193281(v=vs.100).aspx
ANTLRhttp://www.antlr.org/
参考資料 (ScriptDom を使ってる )
チュートリアル : SQL 用のカスタムの静的コード分析規則アセンブリを作成するhttp://msdn.microsoft.com/ja-jp/library/dd172127%28v=vs.100%29.aspx
SQLPSX (PowerShell2 系 /1 世代前の ScriptDom)http://sqlpsx.codeplex.com/