ことの発端は仕事でテーブルの変更を加えた際に200件を超えるINSERT文を修正しなければいけない可能性が出たこと。可能性で終わった(偶然僕は休みだったので)のだが、今後こういったケースが出ないとは限らない。というかDBを弄る必要がある以上起きる。毎回手作業で貴重な人生を浪費するのも馬鹿らしいので、プログラムにやらせてしまいたい。テキスト処理でやるには荷が重過ぎるのでAST(リストだけど)を操作したい。とここまでが動機。
SQLのBNFはここにあるのを使うとして(SQL2003と多少古いが問題ないだろう)、まずはどういう形にするかをまとめておきたい。これがまとまってないから頓挫してるリポジトリもあったりするし・・・
SQLをS式にするというのはいくつか既にあって、たとえばCL-SQLとかSxQLとかS-SQLとか、大体似てるんだけどちょっとずつ違う感じのS式を使用してる。例で挙げたのは全てCLなのでキーワードをSQLのキーワード、select等、に割り当ててるのもあるのだが、Schemeということでそれは避ける方向にする。キーワードでもいいんだけどリーダーのモードで読み込みが変わっちゃうので依存しないようにしたい。
いろいろ悩んだ結果こんな感じで割り付けることにする
- 予約語:シンボル
- テーブル名、カラム名(識別子):シンボル
- 文字列:文字列
- 数値:数値
- ステートメント:リスト
- 式:前置リスト
- 関数呼び出し:前置リスト(式ではないもの)
(select ((count *)) (from foo) (where (and (< 1 id) (< id 10))) ;; = select count(*) from foo where (1 < id and id < 10);他の文は適宜考えることにする。IS NOT NULLみたいなのはどうしようかなぁと悩み中。多分
(not (null? ...))
みたいにする。パーサは軽く書いたけどずっと大変なんだよなぁ。BNFがあるのでpackratを使ってゴリゴリ書いていくつもりではあるが。とりあえず全く必要なさそうなEmbedded SQLとかはばっさり切ってしまって問題ないだろう。後は適当に何とかするしかないかなぁ。
割とすぐ欲しいけど時間がかかりそうだ。頑張ろう・・・
2 comments:
Gaucheにもtext.sqlという書きかけ放置案件が… 識別子はdelimitedのもシンボルにしちゃいます?
delimitedありましたね。単にシンボルにするとSQL文字列にするときに識別できずに困るので文字列か、 (! delimited) みたいなのかなぁ。
Post a Comment