mk2

December 19, 2024

Redmine Query Languageを考えてみる

Redmine Adventer Calendar 2024の12月20日分の記事です。

-----

どうもmk2です。

JiraにはJiraクエリ言語というものがありますが、Redmineにおいてそのようなものを聞いたことがありません。フィルタ実行時のクエリパラメータがある種それに近しいものである気もしますが、可読性は良くないと思います。

今回はそんなJQLに似た、RQL(Redmineクエリ言語)を少しだけ夢想してみようという記事です。

今回のリポジトリ: https://git.sr.ht/~mk2/rql (Redmine 6、Ruby3以上前提)

どういうものになるのか

完成したもののスクショを以下に示します。

image.png


このように、RQLで書いたクエリに応じてチケット情報が検索できるという感じです。

1. 文法を考える

JQLは色々なことができる文法を持っていますが、それと同等のものを作るのは大変なので、以下の2つに絞ります。

  • プロジェクト名で検索できる
  • チケットタイトル名で検索できる
  • それぞれをAND/ORで繋げられる

これをRubyでパーサーを生成できるraccの文法で表現すると下記のようになります。

rule

  statement
    : expression { result = val[0] }
  ;

  expression
    : term
    | expression 'AND' term { result = [:AND, val[0], val[2]] }
    | expression 'OR' term  { result = [:OR, val[0], val[2]] }
  ;

  term
    : IDENT operator value { result = [val[1], val[0], val[2]] }
  ;

  operator
    : '='
    | '!='
    | '<'
    | '<='
    | '>'
    | '>='
    | '~'
  ;

  value
    : STRING
    | NUMBER
    | IDENT
  ;

これの詳細を説明すると下記のような感じになります。(一部ChatGPTに書かせてます)

この文法には以下の要素があります。

  1. statement(文)
    文全体を表すエントリポイントです。

    • 文法的には単一のexpression(式)を受け入れ、結果を返します。
  2. expression(式)
    論理演算(ANDやOR)を含む複合的な条件式を定義します。

    • 単一のterm(項)またはANDやORで結合された複数の式を扱います。
    • 例: x > 10 AND y <= 5
    • この場合、[:AND, [:>, "x", 10], [:<=, "y", 5]]のような形で評価されます。
  3. term(項)
    単純な条件式を定義します。

    • 項は、変数や値の比較を表します。
    • 例: x = 42
    • この場合、[:=, "x", 42]のような形で評価されます。
  4. operator(演算子)
    使用可能な比較演算子を定義しています。

    • 例: =, !=, <, <=, >, >=, ~
    • これらを使って値を比較します。
  5. value(値)
    比較の対象となる値を表します。

    • 値は文字列(STRING)、数値(NUMBER)、または識別子(IDENT)で構成されます。

この文法を使うと、次のような条件式をパースできます。

入力式

x = 42 AND y != "hello"

解析結果

[:AND, 
  ["=", "x", 42], 
  ["!=", "y", "hello"]
]

使えそうですね。

2. 実装を考える

1でraccでパーサーを書いたので、RQLがASTに変換できるようになりました。それを実行できる仕組みを考えます。

https://git.sr.ht/~mk2/rql/tree/master/item/lib/rql/query_executor.rb

こんな感じになります。(雑)

ASTは木構造なので、それを根から順番になぞっていくというシンプルな感じです。なぞりつつ、RailsのActiveRecordのwhereで使える形を作っていきます。

ASTからSQLを直接生成して、それを使えるようにする形もありな気がしますが、こういうクエリ条件式を記述するだけのものだとそこまで必要ないのかなという気がしています。むしろASTを愚直になぞる構造にしておくことで、JQL関数のようなものが実現しやすくなるのかな…と思ったりしてます。

なお、文法もまだきっちり作りこんでいるわけではないので、かなり限定的な使いかたしかできないと思います。

まとめ

JQLに似たRedmine Query Languageを考えてみました。まだまだ道半ばですが、今後もちょいちょい時間をぬって取り組んでいこうと思います。

About mk2

Web Technology Engineer in Japan

About: mk2.red