S-JIS[2023-10-07]

Tsubakuro ResultSet

TsurugiTsubakuro(Java通信ライブラリー)のSqlClientのResultSetのメモ。


概要

TsubakuroのResultSetは、select結果を取得するクラス。

ResultSetはTransactionexecuteQueryメソッド(のFutureResponse)から 取得する。
ResultSetから各レコード・各カラムの値を取得する。
ResultSetは使い終わったらクローズする必要がある。


ResultSetを使用する例

import java.util.List;
import java.util.concurrent.TimeUnit;

import com.tsurugidb.sql.proto.SqlCommon.Column;
import com.tsurugidb.tsubakuro.sql.ResultSet;
    // トランザクション開始
    var option = TransactionOption.newBuilder().setType(TransactionType.SHORT).build();
    try (Transaction transaction = sqlClient.createTransaction(option).await(3, TimeUnit.SECONDS)) {

        // select実行
        String sql = "select * from test";
        try (ResultSet rs = transaction.executeQuery(sql).await(3, TimeUnit.SECONDS)) {
            List<? extends Column>  columnList = rs.getMetadata().getColumns();
            while (rs.nextRow()) {
                for (int i = 0; rs.nextColumn(); i++) {
                    Column column = columnList.get(i);
                    if (rs.isNull()) {
                        System.out.printf("%s: null%n", column.getName());
                    } else {
                        switch (column.getAtomType()) {
                        case INT4: // int
                            int int4 = rs.fetchInt4Value();
                            System.out.printf("%s: %d%n", column.getName(), int4);
                            break;
                        case INT8: // bigint
                            long int8 = rs.fetchInt8Value();
                            System.out.printf("%s: %d%n", column.getName(), int8);
                            break;
                        case CHARACTER: // charやvarchar
                            String string = rs.fetchCharacterValue();
                            System.out.printf("%s: %s%n", column.getName(), string);
                            break;
                        default:
                            throw new UnsupportedOperationException(column.toString());
                        }
                    }
                }
            }
        }

        // selectのみのトランザクションでも、必ずコミットする
        transaction.commit().await(10, TimeUnit.SECONDS);
    }

selectの実行結果(複数レコード)を取得するには、まず、ResultSetのnextRowメソッドを呼び出す。
trueが返るとレコードが有るので、trueである間ループする。

次に、ResultSetのnextColumnメソッドを呼び出す。
trueが返るとカラムが有るので、trueである間ループする。
これによりselect結果レコードのカラムを移動していく。

カラムの値がnullかどうかは、ResultSetのisNullメソッドで判定する。
null以外の場合、カラムの値はfetch系メソッドで取得する。(なぜgetというメソッド名でないかと言うと、一度しか取得できないから)
fetch系メソッドは、カラムのデータ型に一致しているメソッドを使用する必要がある。

カラムのデータ型やカラム名は、ResultSetのgetMetadataメソッドで取得できる。
select文でカラムに名前が付けられていない場合、カラム名はnullになる。(Tsurugiサーバー側で暗黙の名前を付けてくれない)


ResultSetから汎用的に読もうとすると、メタデータからデータ型をチェックする必要があり、全てのデータ型に対応する必要が生じてswitch文が長くなってしまうorz
(なお、Iceaxeはこういったことを行ってくれるので、Iceaxeを使う方が便利)

select結果の各カラムのデータ型が事前に分かっているのなら、メタデータからデータ型を取得する必要は無い。

        // select実行
        String sql = "select pk /*int primary key*/, value /*bigint*/ from test";
        try (ResultSet rs = transaction.executeQuery(sql).await(3, TimeUnit.SECONDS)) {
            while (rs.nextRow()) {
                rs.nextColumn();
                int pk = rs.fetchInt4Value();
                rs.nextColumn();
                Long value = rs.isNull() ? null : rs.fetchInt8Value();
                System.out.printf("%d, %d%n", pk, value);
            }
        }

select文からプログラムを生成するツールやフレームワークなら、こういったソースコードを生成するのが良さそう。


SqlClientへ戻る / Tsubakuroへ戻る / Tsurugiへ戻る / 技術メモへ戻る
メールの送信先:ひしだま