Java/GradleでANTLRを使い、DDLからテーブル定義書を作成、その1

2019年9月27日

ゴール:DDL文からテーブル定義書を自動生成

さて、今回ANTLRを使おうと思ったのは、SQLのDDL文からテーブル定義書を自動作成したいからだ。

例えば、こんなDDLがあるとする(MYSQL)。

/* 書籍テーブル */
create table tbl_book (
  /* 本のID */
  bk_id bigint auto_increment primary key

  /* 書籍名称 */
  ,bk_name text not null

  /* 著者名称 */
  ,bk_author varchar(256) not null
);

あるいはこうだ。

/* 2019/10/1:256では足りないので1024に変更 */
alter table tbl_book modify bk_author varchar(1024) not null;

これらのDDLを読み込んでテーブル定義書を自動生成したいという要求だ。

  • 書籍テーブル
    • 本のID:bk_id、プライマリキー、自動連番
    • 書籍名称:bk_name、text型 not null
    • 著者名称:bk_author、varchar(1024) not null、2019/10/1:256では足りないので1024に変更。

既存ライブラリの利用

もちろん、SQLを解析するJavaライブラリもあるようだが、insertやselectの処理は一切必要無い。create tableとalter tableのみ処理できればよい。しかも、それらのライブラリとは着目点が全く異なる。ここでは、「コメントを拾えること」が重要になるわけだ。

さらに、ANTLR用のMYSQL構文定義もある。これはMySQL Workbenchのコードの一部だ。

こんな大それたものは必要無い、やりたいことは非常に単純なことなので。

しかし、とりあえず、この定義からパーサーを作ってみることにする。

MySQL Workbenchの定義からパーサーを作成してみる

結論から言えば、これはうまく行かなかった。というのも、MySQL WorkbenchはC++製であり、C++で記述された他のファイルが必要になるからだ。以下では無理やりJavaコードを生成しているが、当然クラスが足らないのでコンパイルできない。

ともあれ、以下の手順になる。

ここから、以下のファイルを取り出して、prsフォルダに入れる。

  • MySQLLexer.g4
  • MySQLParser.g4
  • predefined.tokens

build-parsers.cmdにあるように、以下のコマンドで生成するようなので、これをアレンジしてみる。

java -Xmx1024m -jar %WB_3DPARTY_PATH%\bin\antlr-4.7.1-complete.jar -Dlanguage=Cpp -listener -visitor -o ../mysql -package parsers MySQLLexer.g4 MySQLParser.g4

このantlr-4.7.1-complete.jarというのは、antlr本体jarに外部ライブラリを組み合わせて一つのjarにしたものにすぎないようだ。したがって、Gradleでも実行できる。

実は、gradleのantlrプラグインで上記と同じパラメータを指定する方法が不明なため、antlrプラグインを使うのはやめた。直接antlrのmainを呼び出すことにする(他のgradleプラグインについてもそうなのだが、マニュアルが不可解でさっぱり理解できない)。

build.gradleを以下にする。

apply plugin: 'java'
apply plugin: 'eclipse'

repositories {
  jcenter()
}

sourceSets {
  main {
    java.srcDirs = ['src', 'src2']
  }
}

task genParser(type:JavaExec) {
  main = 'org.antlr.v4.Tool'
  classpath = sourceSets.main.output + configurations.compileClasspath
  args '-Dlanguage=Java', '-listener', '-visitor', 
    '-o', 'src2/com/gwtcenter/parsers', 
    '-lib', 'prs',
    '-package', 'com.gwtcenter.parsers',
    'prs/MySQLLexer.g4', 'prs/MySQLParser.g4'  
}

dependencies {
  implementation "org.antlr:antlr4:4.7.2"
}

あとは、gradleでgenParserを実行すれば、以下の状態になる。ファイルが不足しているのでエラーが出ている。

Positive Technologies MySQL grammarからパーサーを作成してみる

もうひとつあった。これを作成してみる。

以下のファイルを取り出し、prsフォルダに入れる。

  • MySqlLexer.g4
  • MySqlParser.g4

build.gradleを次に変更

apply plugin: 'java'
apply plugin: 'eclipse'

repositories {
  jcenter()
}

sourceSets {
  main {
    java.srcDirs = ['src', 'src2']
  }
}

task genParser(type:JavaExec) {
  main = 'org.antlr.v4.Tool'
  classpath = sourceSets.main.output + configurations.compileClasspath
  args '-Dlanguage=Java', '-listener', '-visitor', 
    '-o', 'src2/mysqlparser', 
    '-package', 'mysqlparser',
    'prs/MySqlLexer.g4', 'prs/MySqlParser.g4'  
}

dependencies {
  implementation "org.antlr:antlr4:4.7.2"
}

gradleでgenParserを実行すると、以下になる。

エラーは出ていない。次回はこれを使って目的が達成できるか検証してみる。