空谷に吼える

ブロックチェーン/DLTまわりのなにかしらを書いていく所存

Oracle Database 23cでBlockchain Tableのカラム追加/削除が可能になったので試す

Blockchain Tableのカラムの追加/削除

Oracle Databaseの23cが(プラットフォームごとに順次)リリースされています。で、23cのBlockchain Table関連の機能強化として、"Blockchain Tableのカラムの追加と削除が可能になった"というのがあります。

Blockchain Tableは一度書き込まれたデータの改ざんを防ぎ、また、行をハッシュチェーンでつなげていくことで改ざんがないことを検証可能にする、といった特性の都合か、以前のバージョンでは通常のテーブルと異なりカラムの追加や削除ができませんでした(カラムの追加や削除を禁止する制約がありました)。そのため、業務要件の変化などでデータ項目を増やしたい/減らしたいといったニーズに対応することが難しく、そうしたニーズが生じる可能性がある場合にはカラムに開くのではなくJSON型でデータを持っておくなどの回避策が必要でした。

23cで新たに導入されたBlockchain Tableのバージョン"V2"では、カラムの追加と削除が可能になりました。業務要件の変化によるデータ項目の変更などに、より柔軟に対応できることになります。

また、23c新機能ガイドには以下のように紹介されています。カラムを削除した場合にも、削除以前のデータを含めハッシュチェーンの検証が問題なく行えるように、削除したカラムのデータを保持してくれるようですね。良さそうです。

ブロックチェーン表および不変表でのユーザー列の追加および削除 この機能により、ブロックチェーン表および不変表の発展が可能になります。つまり、暗号ハッシュ・チェーンの継続のために削除された列のデータを含め、現在のデータを維持しながら列を追加および削除できます。

アプリケーションの発展に伴い、列を追加または削除して既存の表を変更する必要がある場合があります。このリリースでは、以前に作成したブロックチェーン表または不変表の列を簡単に追加または削除できます。列の削除前の行は、暗号ハッシュ・チェーンの整合性を維持し、検証手順が表全体で機能できるように、これらの列のデータを保持します。

試してみよう

ということで実際どんな動きをするのか試してみましょう。

V1ではできないことを確認

まずはカラム追加/削除ができないはずの、Blockchain Tableのバージョン"V1"で試してみます。まず適当なBlockchain TableをVERSION "V1'指定で作成し、適当な行をINSERTしてCOMMITしておきます。

drop table if exists bct1 purge;

create blockchain table bct1 (
  id           number,
  desc1        varchar2(50),
  constraint bct1_pk primary key (id)
)
no drop until 0 days idle
no delete locked
hashing using "SHA2_512" version "V1";

insert into bct1 values (1, 'aaaa') ;
insert into bct1 values (2, 'bbbb') ;
commit;

で、ALTER TABLE ADD/DROP COLUMNしてみると……

alter table bct1 add desc2 varchar2(50);
alter table bct1 drop column desc1;

いずれも以下のエラー(ORA_05715)になりました。

エラー・レポート -
ORA-05715: 操作はブロックチェーンまたは不変表では許可されていません
05715. 0000 -  "operation not allowed on the blockchain or immutable table" 
*Cause:    The table was insert-only table and, therefore, could not be
           updated or deleted.
*Action:   No action required.

ということで、Blockchain TableのバージョンV1ではカラムの追加/削除は禁止されておりできません。

V2でできるようになったことを確認

ではカラム追加/削除ができるようになったはずのBlockchain Tableのバージョン"V2"で試してみます。まず適当なBlockchain TableをVERSION "V2'指定で作成し、適当な行をINSERTしてCOMMITしておきます。

drop table if exists bct1 purge;

create blockchain table bct1 (
  id           number,
  desc1        varchar2(50),
  constraint bct1_pk primary key (id)
)
no drop until 0 days idle
no delete locked
hashing using "SHA2_512" version "V2";

insert into bct1 values (1, 'aaaa') ;
insert into bct1 values (2, 'bbbb') ;
commit;

で、ALTER TABLE ADDでカラムを追加してみると成功します。やったぜ。さすがV2。

alter table bct1 add desc2 varchar2(50);

Table BCT1が変更されました。

なお、ここでselect * from bct1;してみると、新たに追加したdesc2の値はどの行でもnullになっています(デフォルト値を指定していないため)。

また、↓のようにハッシュチェーンの検証を行ってみると成功しました。カラム追加後にも既存の行のハッシュチェーンの検証が問題なく行えたということです。

set serveroutput on
declare
  l_rows      number;
  l_verified  number;
begin
  select count(*)
  into   l_rows
  from   bct1;

  dbms_blockchain_table.verify_rows(
    schema_name             => 'BCTTEST',
    table_name              => 'bct1',
    number_of_rows_verified => l_verified);

  dbms_output.put_line('Rows=' || l_rows || '  Verified Rows=' || l_verified);
end;

次にALTER TABLE DROP COLUMNしてみましょう。これも成功しました。やったぜ。

alter table bct1 drop column desc1;

Table BCT1が変更されました。

ここで同様に、↑のハッシュチェーンの検証を行ってみたところ成功しました。新機能ガイドの記載にあった通り、カラムを削除した後にも、既存の行の削除したカラムのデータが裏側に保持されていて、ハッシュチェーンの検証は問題なく行えるようです。さすがV2。アサルトバスターのリリースも待ち遠しいですね。

追加するカラムにデフォルト値を指定することはできる?

前述の通り、デフォルト値を指定しない場合、既存行の追加カラムの値はnullになります。

ではデフォルト値を指定するとどうなるでしょうか?結論から言うとバージョンV2でもBlockchain Tableに対してデフォルト値を指定してのカラム追加はできません。制約として覚えておきましょう。以下、具体的な検証方法と結果です。

以下のように、既にいくつかの行をINSERT済のバージョンV2のBlockchain Tableに対し、デフォルト値を指定しつつカラムの追加を試みます。

drop table if exists bct1 purge;

create blockchain table bct1 (
  id           number,
  desc1        varchar2(50),
  constraint bct1_pk primary key (id)
)
no drop until 0 days idle
no delete locked
hashing using "SHA2_512" version "V2";

insert into bct1 values (1, 'aaaa') ;
insert into bct1 values (2, 'bbbb') ;
commit;

alter table bct1 add desc3 varchar2(50) default 'aaa';

すると以下のようなエラーになり失敗します。

エラー・レポート -
ORA-00604: 再帰SQLレベル1でエラーが発生しました。
ORA-05715: 操作はブロックチェーンまたは不変表では許可されていません
00604. 00000 -  "error occurred at recursive SQL level %s"
*Cause:    An error occurred while processing a recursive SQL statement
           (a statement applying to internal dictionary tables).
*Action:   If the situation described in the next error on the stack
           can be corrected, do so; otherwise contact Oracle Support.

ORA-00604なので内部でなんかやっている中で使ったSQLがBlockchain Tableの制約に引っかかっているっぽいですね。

「既に存在する行の追加カラムの値をデフォルト値に更新するためにUPDATEしようとしてエラーになっているのかな?」と思い、以下のようにテーブルを作成後に何もINSERTしない状態でデフォルト値指定しつつカラム追加してみると……

drop table if exists bct1 purge;

create blockchain table bct1 (
  id           number,
  desc1        varchar2(50),
  constraint bct1_pk primary key (id)
)
no drop until 0 days idle
no delete locked
hashing using "SHA2_512" version "V2";

alter table bct1 add desc3 varchar2(50) default 'aaa';

やはり同様のエラー(ORA-00604)が発生しました。なるほど……?まあそもそも(NO DROP UNTIL n DAYSの指定に関わらず)ひとつも行をINSERTしてない状態ならBlockchain Tableと言えどDROP TABLEできるので、テーブルを作り直しましょうね。