VoltDBの開発者向けドキュメントのまとめ(7章:アプリケーション開発の簡略化)


はじめに

VoltDBの開発者向けの公式ドキュメントUsing VoltDBのまとめです。対象のバージョンはv8.3です。
正確に翻訳することや網羅することは目的ではないため、重要でない記述等は削除したり、不足部分は追記しています。

今回は7章です。

現時点でまとめたのは以下の章です。
3. データベースの起動
7. アプリケーション開発の簡略化
9. クラスタでVoltDBを使用する
13. VoltDBデータベースの保存と復元

なお、本投稿のまとめ元である「Using VoltDB」のライセンスはAGPLであり、これらのまとめ投稿はAGPLが適用されます。

7. アプリケーション開発の簡略化

・VoltDBには開発を容易にする以下の3つの機能がある。

  • デフォルトプロシージャの利用
  • 単純なストアドプロシージャを定義するためのショートカット
  • 期待されるクエリ結果の確認

7.1. デフォルトプロシージャの利用

・キーに基づいてレコードをinsert、select、update、deleteする単純な操作を簡単に実行するために、VoltDBには各テーブルにデフォルトストアドプロシージャを自動で定義する。
・デフォルトのストアドプロシージャでは、「テーブル名.ステートメント」の名前がで定義される。たとえば、HELLOWORLDというテーブルでは、以下のデフォルトストアドプロシージャを自動で定義される。

・全てのテーブルでinsertを実行するデフォルトストアドプロシージャが作成される。

  • HELLOWORLD.insert: パラメータはテーブルの列と同じ順序。

・テーブルに主キーがある場合は、update、upsert、deleteをデ実行するデフォルトストアドプロシージャが作成される。

  • HELLOWORLD.update: パラメータはテーブルの列と同じ順序。その後に主キー値が続く。つまり、主キー値は2回指定される。
  • HELLOWORLD.upsert: パラメータはテーブルの列と同じ順序。
  • HELLOWORLD.delete: パラメータは主キー値。複合主キーの場合は定義の順序となる。

・テーブルに主キーがありパーティション化されている場合、selectを実行するデフォルトストアドプロシージャが作成される。
HELLOWORLD.select : パラメータは主キー値。複合主キーの場合は定義の順序となる。

sqlcmdコマンドのshow proceduresを使用して、使用可能なすべてのストアドプロシージャをリストし、必要なパラメータの数と種類を指定します。

[補足] show proceduresの実行例

# sqlcmd
1> show procedures
~省略~
--- User Procedures ------------------------------------------
KEISOKU_DATA.delete             varchar, timestamp
KEISOKU_DATA.insert             varchar, timestamp, smallint, smallint, smallint, smallint, smallint, timestamp, varchar
KEISOKU_DATA.select             varchar, timestamp

・コード例

VoltTable[] results;
client.callProcedure("HELLOWORLD.insert",
                     "American","Howdy","Earth");
results = client.callProcedure("HELLOWORLD.select",
                     "American").getResults();
client.callProcedure("HELLOWORLD.update",
                     "American","Yo","Biosphere",
                     "American");
client.callProcedure("HELLOWORLD.delete",
                     "American");

7.2. 単純なストアドプロシージャを定義するためのショートカット

・1つのSQLクエリを実行して呼び出し元のアプリケーションに結果を返すだけでよい単純なケースでは、ストアドプロシージャのJavaコードを書くのは面倒な作業なので、VoltDBではショートカットを提供している。
・ショートカットでは、ストアドプロシージャをデータベーススキーマの一部として定義できる。
・通常、ストアドプロシージャはJavaのクラスから以下のように定義する。

CREATE PROCEDURE FROM CLASS MakeReservation;
CREATE PROCEDURE FROM CLASS CancelReservation;

・ショートカットでは、以下のようにAS句にSQLクエリを記述して定義できる。

CREATE PROCEDURE CountReservations AS
    SELECT COUNT(*) FROM RESERVATION;

・単純なストアドプロシージャでは、以下のようにSQLクエリへ引数を渡すこともできる。

CREATE PROCEDURE MyReservationsByTrip AS
        SELECT R.RESERVEID, F.FLIGHTID, F.DEPARTTIME
        FROM RESERVATION AS R, FLIGHT AS F
        WHERE R.CUSTOMERID = ?  
        AND R.FLIGHTID = F.FLIGHTID
        AND F.ORIGIN=? AND F.DESTINATION=?;

・単純なプロシージャーをシングルパーティションにするかどうかを指定することもできる。
・デフォルトでは、ストアド・プロシージャはマルチパーティションと見なされる。
・シングルパーティションにする場合は、PARTITION ON句でそのパーティションを指定する。

CREATE PROCEDURE FetchReservations 
   PARTITION ON 
      TABLE Reservation COLUMN flightid
   AS
      SELECT * FROM RESERVATION WHERE FLIGHTID=?;

・単純なプロシージャ内で複数のSQL文を実行する場合は、SQLをBEGIN-END句に囲む。

CREATE PROCEDURE OpenOrders
   AS BEGIN
      SELECT fullname FROM CUSTOMER WHERE CUSTOMERID=?;
      SELECT * FROM ORDER WHERE CUSTOMERID=?;
   END;

・各ステートメントはセミコロン(;)で終了する。
・プロシージャは、プロシージャ内の各文に対するVoltTableの配列を返す。
・引数は再利用されないので、上の例ではCUSTOMERIDの値を2回引数に与えて実行する。

7.3. 期待されるクエリ結果の確認

・クエリによって返される結果の正確性を検証するためにコーディングが必要となる場合がある。例えば、正しい数のレコードを取得したか?クエリは正しい値を返したか?
・VoltDBはクエリの結果を手動で検証するコードを記述するのではなく、クエリ自体に検証を実行する方法を提供する。
・クエリが検証で期待値とならない場合、ストアドプロシージャは自動的にVoltAbortExceptionをスローしてロールバックされる。

・期待値を指定する場合、voltQueueSQLメソッドの2番目のパラメータに指定する。
・次のコードは、EXPECT_ONE_ROWの期待値を使用して1レコードだけが返ってくることを検証している。

import org.voltdb.Expectation;
           .
           .
           .
public final SQLStmt GetSeats = new SQLStmt(
        "SELECT numberofseats FROM Flight WHERE flightid=?;");

voltQueueSQL(GetSeats, EXPECT_ONE_ROW, flightid); -- EXPECT_ONE_ROWで検証
VoltTable[] recordset = voltExecuteSQL();
Long numofseats = recordset[0].asScalarLong();

・このように期待値を使用することにより、結果に1行しか存在しないことを検証するためのエラー・チェックを行う必要がなくなる。

・次の表は、ストアドプロシージャで使用できるすべての期待値を示す。

期待 説明
EXPECT_EMPTY クエリはレコードを返されない。
EXPECT_ONE_ROW クエリは1レコードのみを返す必要があります。
EXPECT_ZERO_OR_ ONE_ROW クエリは、0個以上のレコードを返す必要があります。
EXPECT_NON_EMPTY クエリは少なくとも1レコードを返す必要があります。
EXPECT_SCALAR クエリは単一の値(1列のみ)を返す必要があります。
EXPECT_SCALAR_LONG クエリは、Long型のデータ型を持つ単一の値を返す必要があります。
EXPECT_SCALAR_MATCH(long) クエリは、指定されたLong値に等しい単一の値を返す必要があります。