Beyond the State-of-the-Art

最先端を超えたいと思ってる(大嘘)エンジニアのブログ

【OSS貢献記録】ClickHouse公式JDBCドライバでバインド済みのprepared statementを出力する関数を実装

Qiitaからの移植です。

はじめに

ClickHouseというYandex社が中心となって開発しているOSSのDBMSがあります。ClickHouse公式でJDBCドライバが開発されています。

私は昨年このJDBCドライバのリポジトリに対して、プルリク Enable to get a bound statement in ClickHousePreparedStatement #282 を出しました。このプルリクは無事にmasterブランチにマージされました。

私が第三者が管理するOSSでソースコードで貢献したのはこれが初めてです。いまさらですが、このプルリクの内容を簡単に説明しようと思います。

プルリクの内容

概要

簡単にいうと、prepared statementで値をバインドしたときのSQLを出力する関数を実装しただけです。

例えば下記のコードのように、プレースホルダーに値をバインドしたとします。

String unboundStatement = "SELECT test.example WHERE id IN (?, ?)";
// connectionはClickHouseとの接続オブジェクト
ClickHousePreparedStatement statement = (ClickHousePreparedStatement) 
    connection.prepareStatement(unboundStatement);
statement.setInt(1, 123);  // 1つ目のプレースホルダーに値123をバインド
statement.setInt(2, 456);  // 2つ目のプレースホルダーに値456をバインド

ちゃんと値がバインドされているかどうか確認するために、デバッグ出力で

SELECT test.example WHERE id IN (123, 456)

になっているかどうかを見たいと思いました。しかし、値がバインドされた後のSQLを出力するための関数がClickHousePreparedStatementクラスにありませんでした。そこでClickHousePreparedStatementtoSqlというメンバ関数を追加し、値がバインドされた後のSQLを文字列として取得できるようにしました。

ClickHousePreparedStatement#toSqlの仕様

さきほどのコード例を出すと、何も値をバインドしていないときはtoSqlから

SELECT test.example WHERE id IN (?, ?)

が文字列として返ってきます。

statement.setInt(1, 123);
statement.setInt(2, 456);

で値をすべてバインドした後でtoSqlを実行すると

SELECT test.example WHERE id IN (123, 456)

が返ってきます。

仮に全部の値をバインドしない、例えばstatement.setInt(1, 123)だけ実行してstatement.setInt(2, 456)を実行しない場合は、何もバインドされていない場合のSQL

SELECT test.example WHERE id IN (?, ?)

が返ってきます。本当は

SELECT test.example WHERE id IN (123, ?)

が返ってくるようにしたかったのですが、実現しようとすると、SQLを組み立てる関数の例外を出し方を変える等影響範囲が広い改修をする必要になるので、諦めました。

おまけ

プルリク内の追加したテストコードで変数unbindedStatementがありますが、綴りがおかしいですね。正しくはunboundStatementです。