[[JAVAの記事一覧]]
*目次 [#pccd97cd]
#contents


*Java SQL Parserを調査する [#zb549a4a]


*動機 [#d8f88e2b]
SQLを解析することで、SQLを動的に解析して単体試験仕様書の作成を自動化したい

そのためには次の項目を自動抽出したい。

*自動抽出希望項目 [#y3bf4f8c]
-変数

Oracleのプレースホルダー
-テーブル
-検索条件
-結果項目

さらにいうと、
-検索条件が外部結合なのかどうなのか
-結果項目が外部結合の項目なのかどうなのか




*Java SQL Parser [#tc368e00]
**ANTLR [#d305b35b]
http://www.antlr.org/grammar/list

***特徴 [#zd36fbf9]
-ANSI SQL 文法に則っているらしい
-本格的なツールだが、学習コストが高い。
-過去のコードは微調整が必要なので、修正できるだけの文法知識が必要
-英語の本が出版されている模様
-グラフィカルなIDEはJREがインストールされていればダブルクリックで動作する

***使い方 [#y4a50bfe]
よくわからない状態で、ためしにEclipseのビルドパスに外部Jarとしてぶっこんで、

http://www.antlr.org/wiki/display/ANTLR3/ANTLR+Cheat+Sheet

をためしてみたが、TLexerとTParserが見つからない、どうやら事前に生成するようだ。

***expr.g [#b5fa1b0a]
expr.gで下記の内容を保存してみる。
 class ExprParser extends Parser;
 expr:
  mexpr ((PLUS|MINUS) mexpr)*
  ;
 mexpr:
  atom (STAR atom)*
  ;    
 atom:
  INT | LPAREN expr RPAREN 
  ;

 class ExprLexer extends Lexer;
 options {
    k=2; // needed for newline junk
    charVocabulary='\u0000'..'\u007F'; // allow ascii
 }
 LPAREN: '(' ;
 RPAREN: ')' ;
 PLUS  : '+' ;
 MINUS : '-' ;
 STAR  : '*' ;
 INT   : ('0'..'9')+ ;
 WS    : ( ' '
        | '\r' '\n'
        | '\n'
        | '\t'
        )
        {$setType(Token.SKIP);}
      ;   

次のようにコマンドラインで実行する
 java -classpath antlr-3.2.jar antlr.Tool expr.g

なにやらファイルが生成された

***PLSQLの定義ファイルはこちら [#e34a0fb0]
http://www.antlr.org/grammar/1174072667394/PLSQLGrammar.g

上記ファイルをダウンロードして下記のように打ち込むと
 java -classpath antlr-3.2.jar antlr.Tool PLSQLGrammar.g
クラスファイルが出来上がる。

で、下記のクラスを要求している

-SoftwareMetrics

そのファイルは下記よりダウンロード可である。

***SoftwareMetricsクラスはこちら [#vc0354bc]
http://www.antlr.org/grammar/1174072667394/SoftwareMetrics.java

でこのSoftwareMetricsはいろいろ摩訶不思議な設定が必要だが、その方法は下記よりダウンロード可能
***PLSQLMain [#m1041498]
http://www.antlr.org/grammar/1174072667394/PLSQLMain.java


***eclipse plugin [#i37aa57a]
http://antlreclipse.sourceforge.net/



***使い方の参考URL [#x934b7b7]
http://www.limy.org/program/java/antlr/step1.html

*** [#wa6d7ae4]
http://openjdk.java.net/projects/compiler-grammar/antlrworks/

***感想 [#u57d8490]
-IDEがすばらしい

-JavaSDKの開発者も使ってるんじゃないのか

http://openjdk.java.net/projects/compiler-grammar/antlrworks/

-グラフィック表示がすばらしい
-いろいろな言語へのAPIが提供されている。
-コンパイルすんの?これ。


**Apache Derby. [#dd48fb97]
Apache Derby

http://db.apache.org/derby/

はApacheのDBのサブプロジェクトでしてそのApache Derbyにパーサがあるらしい

.native() メソッドを見るといいようだ。


**JSqlParser [#z990ac26]
http://jsqlparser.sourceforge.net/

SQLを解析してJavaクラスの階層構造に変換するらしい

***使い方:準備 [#v0afcae4]
ダウンロードしてきたjarのパスをzipに変換して解凍し、
そのなかからlibフォルダにjarがあるので、そいつをeclipseのビルドパスに外部jarとして取り込ませる。

***サンプル [#ye6afd41]
サイトのサンプルがちょっと手直しが必要だったので直して、日本語訳しておきます。

TablesNamesFinderのStringValueはEclipseの自動保管を使うとjava.langの方をつかうので、
 import net.sf.jsqlparser.expression.StringValue;
としておきましょう

JoinVisitor(だっけか?)は削除しておきます。



                CCJSqlParserManager pm = new CCJSqlParserManager();
		/*
		 * Oracleのプレースホルダーは対応してないので、''で括るなどしましょう
		 * :AAA -> ':AAA' 
		 * Oracleの外部結合である(+)も対応していないので、削っておきましょう
		 * (+) -> 削除 
		 */
		String sql = "SELECT * FROM MY_TABLE1, MY_TABLE2, (SELECT * FROM MY_TABLE3) LEFT OUTER JOIN MY_TABLE4 "+
		" WHERE ID = (SELECT MAX(ID) FROM MY_TABLE5) AND ID2 IN (SELECT * FROM MY_TABLE6)" ;
		net.sf.jsqlparser.statement.Statement statement = pm.parse(new StringReader(sql));
		/* 
		対象のSQL文字列が何を行うか(たとえばSELECTなのかINSERTなのか...)に応じて、
		StatementVisitorをimplementsで実装したクラスをつかってください。
		とりあえずここでは例としてSELECT用のselectStatementをつかっています。
		*/
		if (statement instanceof Select) {
			Select selectStatement = (Select) statement;
			TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
			List tableList = tablesNamesFinder.getTableList(selectStatement);
			for (Iterator iter = tableList.iterator(); iter.hasNext();) {
				System.out.println(iter.next());
			}
		}




**Zql [#cb147f36]
http://www.gibello.com/code/zql/

Javaで書かれたSQLのParser

**BYACC/J [#hf6fdc85]
http://byaccj.sourceforge.net/

YACCと互換性あるそうな。



**Java Cup [#f82fb0f2]
http://www2.cs.tum.edu/projects/cup/

JavaのParser生成ライブラリー

**JFlex [#s987734b]
JFlexはこちら

http://jflex.de/


**jparsec [#e9851712]
http://jparsec.codehaus.org/

YACCのような位置づけである。

YACCとの違いは外部ファイルを必要としないとか。
トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS