JAVAの記事一覧

目次

Java SQL Parserを調査する

動機

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

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

自動抽出希望項目

Oracleのプレースホルダー

さらにいうと、

その他達成しようとしていること

SQLを解析し、Excelで定義してある和名を検索し和名表示に置換する。

そのためには、SQL解析にて、次の対応表を作成する。

テーブルの別名とテーブル名

テーブル名とテーブル和名

WHERE句などの解析方法について考える

WHERE句を解析するには正規表現などを駆使して文法を解析するのもいいが、できれば文法の定義ファイルをもとにパーサを生成し、そのパーサをもとに解析したい。

全体的な感想

簡単な文法レベルでいいから手軽にパーサを生成して活用できるようになりたいと思う。

Java SQL Parser

ANTLR

http://www.antlr.org/grammar/list

まずは上記のFAQから読み始めたほうがいいが、英語なので、英語が苦手ならば、日本語の説明サイトがあったので、そちらをみたほうがいい。

使い方の参考URL

http://www.limy.org/program/java/antlr/step1.html

特徴

使い方

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

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

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

expr.g

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の定義ファイルはこちら

http://www.antlr.org/grammar/1174072667394/PLSQLGrammar.g

上記ファイルをダウンロードして下記のように打ち込むと

java -classpath antlr-3.2.jar antlr.Tool PLSQLGrammar.g

クラスファイルが出来上がる。

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

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

SoftwareMetrics?クラスはこちら

http://www.antlr.org/grammar/1174072667394/SoftwareMetrics.java

でこのSoftwareMetrics?はいろいろ摩訶不思議な設定が必要だが、その方法は下記よりダウンロード可能

PLSQLMain

http://www.antlr.org/grammar/1174072667394/PLSQLMain.java

eclipse plugin

http://antlreclipse.sourceforge.net/

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

感想

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

Apache Derby.

Apache Derby

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

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

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

JSqlParser?

http://jsqlparser.sourceforge.net/

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

特徴

使い方:準備

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

サンプル

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

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

http://www.gibello.com/code/zql/

Javaで書かれたSQLのParser

OracleのDECODEとかの関数がデフォルトで定義されていない

p = new ZqlParser();
p.addCustomFunction("DECODE", 0);

とするが、引数の数値のエラーがでたまま解析が実行できない。

下記のアドレスが参考になりそうだが、MDLがよくわからんので役にはたたない。

http://blogs.oracle.com/warehousebuilder/2007/08/14/

Demoの動かし方

cmd

でDOSプロンプト起動

cd xxxデモのあるディレクトリ

でデモファイルがあるディレクトリをカレントディレクトリにする。

READMEには

java ZDemo queries.num

とあるが、パスを通しておく

java -cp .;..\classes ZDemo queries.num

Demo実行結果

select * from num
[a = 1.0, b = 1.0, c = 1.0, d = 1.0, e = 1.0]
[a = 2.0, b = 2.0, c = 2.0, d = 2.0, e = 2.0]
[a = 1.0, b = 2.0, c = 3.0, d = 4.0, e = 5.0]
[a = 5.0, b = 4.0, c = 3.0, d = 2.0, e = 1.0]
select * from num where ((1 + 1) = 2)
[a = 1.0, b = 1.0, c = 1.0, d = 1.0, e = 1.0]
[a = 2.0, b = 2.0, c = 2.0, d = 2.0, e = 2.0]
[a = 1.0, b = 2.0, c = 3.0, d = 4.0, e = 5.0]
[a = 5.0, b = 4.0, c = 3.0, d = 2.0, e = 1.0]
select ((((a + b) + c) + d) + e) from num
5.0
10.0
15.0
15.0

ちなみにもうひとつのデモを試す

java -cp .;..\classes StringDemo "select * from num where foo = bar order by fuga;"

結果

select * from num where (foo = bar) order by fuga ASC

BYACC/J

http://byaccj.sourceforge.net/

YACCと互換性あるそうな。

Java Cup

http://www2.cs.tum.edu/projects/cup/

JavaのParser生成ライブラリー

JFlex

JFlexはこちら

http://jflex.de/

jparsec

http://jparsec.codehaus.org/

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

YACCとの違いは外部ファイルを必要としないとか。

特徴

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS