2021年4月6日火曜日

APEXからオブジェクト・ストレージをPL/SQL SDKで操作する(3) - オブジェクトの操作

 これからオブジェクトの操作を実装していきます。バケットの実装と同様にパイプライン表関数の実装、レポートとフォームの作成、フォームを処理するプロセスの記述を行います。

バケット内のオブジェクトの一覧を取得するパイプライン表関数list_objectsを定義します。コードは以下になります。

drop type t_object_tbl;
drop type t_object_row;
create or replace type t_object_row as object
(
id varchar2(4000)
, name varchar2(4000)
, l_size number
, md5 varchar2(4000)
, time_created timestamp(6) with time zone
, etag varchar2(4000)
, time_modified timestamp(6) with time zone
)
/
create or replace type t_object_tbl as table of t_object_row
/
/*
* ネームスペース、バケット、リージョンを指定して、そこに含まれるオブジェクトの一覧を取得する。
*/
create or replace function list_objects
(
p_namespace_name in varchar2
, p_bucket_name in varchar2
, p_region in varchar2
, p_credential_name in varchar2
)
return t_object_tbl pipelined
as
response dbms_cloud_oci_obs_object_storage_list_objects_response_t;
object dbms_cloud_oci_object_storage_object_summary_t;
l_object t_object_row;
plsql_sdk_error exception;
begin
response := dbms_cloud_oci_obs_object_storage.list_objects(
namespace_name => p_namespace_name
, bucket_name => p_bucket_name
, region => p_region
, credential_name => p_credential_name
);
if response.status_code != 200 then
raise plsql_sdk_error;
end if;
for i in 1 .. response.response_body.objects.count
loop
object := response.response_body.objects(i);
l_object := t_object_row(
object.name -- nameが一意なのでnameをidとする
, object.name
, object.l_size
, object.md5
, object.time_created
, object.etag
, object.time_modified
);
pipe row(l_object);
end loop;
end;
/
これをSQLワークショップSQLスクリプトに登録し、実行します。実行手順はバケットを一覧するファンクションlist_bucketsで行ったものと同じです。


list_bucketsと同様に初回実行時は先頭の2行はエラーになります。残りの3行成功していれば、ファンクションlist_objectsが作成できています。


続いて、作成したパイプライン表関数を使ったレポートとフォームのページを作成します。作成しているアプリケーションを開き、ページの作成を実行します。


対話モード・レポートを選択します。


ページ定義名前オブジェクト一覧とします。フォーム・ページを含めるONに変更し、フォーム・ページ名オブジェクト操作とします。フォーム・ページ・モードとしてモーダル・ダイアログを選択します。

データ・ソースソース・タイプSQL問合せを選択し、以下のSELECT文を記述します。
select * from list_objects
(
    p_namespace_name => :G_NAMESPACE_NAME
    , p_bucket_name => :P4_BUCKET_NAME
    , p_region => :G_REGION
    , p_credential_name => :G_CREDENTIAL_NAME
)
P4_BUCKET_NAMEはページを作成した後、ページ・アイテムとして作成します。

ナビゲーションブレッドクラムの使用ナビゲーションの使用はともにONにします。

以上を設定し、へ進みます。


主キー列1としてID (Varchar2)を選択し、ページの作成を実行します。


ページが作成された後、対話モード・レポートのリージョンにページ・アイテムを作成します。

ページ・アイテムP4_BUCKET_NAMEを作成します。ページ・アイテムの作成を実行し、作成されたページ・アイテムの識別名前P4_BUCKET_NAMEタイプ表示のみラベルBucket Nameとします。


バケット名バケット一覧から引き継ぎます。バケット一覧を表示するレポートに、オブジェクト一覧をレポートするページへのリンクを作成します。

バケット一覧のページをページ・デザイナで開きます。

NAMEタイプをプレーン・テキストからリンクへ変更し、ターゲットを設定します。リンク・テキスト#NAME#とします。


リンクターゲットとして、オブジェクト一覧のページを指定します。ターゲットタイプこのアプリケーションのページページです。アイテムの設定として、ページ・アイテムのP4_BUCKET_NAMEは列NAMEP4_NAMESPACEには列NAMESPACEの値が渡されるよう設定します。OKをクリックします。


以上でオブジェクトの一覧を表示する設定が完了したので、バケット一覧のページを実行して指定したバケットに含まれるオブジェクトの一覧をリストしてみます。

バケット一覧のページの列Nameがリンクに変わっています。これをクリックします。


選択したバケットに含まれるオブジェクトの一覧画面に遷移します。登録されたオブジェクトが存在しないと、データが見つかりません。と表示されますが、オブジェクトの一覧画面はこれで完成しています。


続いてオブジェクト操作の画面を変更し、オブジェクトの作成/更新/
削除ができるようにします。

ページ・デザイナにてオブジェクト操作のページを開き、オブジェクトの操作に必要なページ・アイテムを2つ作成します。

最初に、バケット名を保持するページ・アイテムP5_BUCKET_NAMEを作成します。アイテムの作成を実行し、識別名前P5_BUCKET_NAMEとし、タイプ非表示にします。


次に、オブジェクト・ストレージにアップロードするファイルを指定するページ・アイテムP5_FILEを作成します。識別名前P5_FILEとし、タイプファイル参照...を選択します。ラベルFilename、それ以外はデフォルトですが、特に記憶域タイプについては、Table APEX_APPLICATION_TEMP_FILESであることを確認します。アップロードされたファイルは、こちらの表より取得します。


必要なページ・アイテムが登録されたので、プロセスを変更します。

左ペインよりプロセス・ビューを開き、プロセス・フォームオブジェクトの操作を選択します。設定ターゲット・タイプPL/SQL Codeに変更し、挿入/更新/削除するPL/SQLコードに以下を記述します。失われた更新の防止OFF行のロックNoにします。

declare
l_rename_object_details dbms_cloud_oci_object_storage_rename_object_details_t;
l_put_response dbms_cloud_oci_obs_object_storage_put_object_response_t;
l_rename_response dbms_cloud_oci_obs_object_storage_rename_object_response_t;
l_delete_response dbms_cloud_oci_obs_object_storage_delete_object_response_t;
l_status_code integer;
l_filename varchar2(4000);
l_content_type varchar2(4000);
l_blob blob;
l_loc number;
plsql_sdk_error exception;
-- 日本語に対応させる
function cs_workaround(str varchar2)
return varchar2
as
begin
return utl_url.escape(str, false, 'AL32UTF8');
end cs_workaround;
begin
case
when :APEX$ROW_STATUS = 'C' then
begin
select filename, mime_type, blob_content into l_filename, l_content_type, l_blob
from apex_application_temp_files
where name = :P5_FILE;
exception
when no_data_found then
l_blob := null;
end;
if lengthb(:P5_NAME) > 0 then
l_filename := :P5_NAME;
end if;
l_filename := cs_workaround(l_filename);
l_put_response := dbms_cloud_oci_obs_object_storage.put_object
(
namespace_name => :G_NAMESPACE_NAME
, bucket_name => :P5_BUCKET_NAME
, object_name => l_filename
, content_type => l_content_type
, put_object_body => l_blob
, region => :G_REGION
, credential_name => :G_CREDENTIAL_NAME
);
l_status_code := l_put_response.status_code;
when :APEX$ROW_STATUS = 'U' then
l_rename_object_details := new
dbms_cloud_oci_object_storage_rename_object_details_t;
l_rename_object_details.source_name := :P5_ID;
l_rename_object_details.new_name := :P5_NAME;
l_rename_response := dbms_cloud_oci_obs_object_storage.rename_object
(
namespace_name => :G_NAMESPACE_NAME
, bucket_name => :P5_BUCKET_NAME
, rename_object_details => l_rename_object_details
, region => :G_REGION
, credential_name => :G_CREDENTIAL_NAME
);
l_status_code := l_put_response.status_code;
when :APEX$ROW_STATUS = 'D' then
l_delete_response := dbms_cloud_oci_obs_object_storage.delete_object
(
namespace_name => :G_NAMESPACE_NAME
,bucket_name => :P5_BUCKET_NAME
,object_name => cs_workaround(:P5_NAME)
, region => :G_REGION
, credential_name => :G_CREDENTIAL_NAME
);
l_status_code := l_put_response.status_code;
end case;
if l_status_code != 200 then
raise plsql_sdk_error;
end if;
end;

作成のときは、ビューAPEX_APPLICATION_TEMP_FILESよりアップロードされたファイルをBLOBとして取り出し、そのBLOBをオブジェクト・ストレージに登録しています。オブジェクト名の入力がなければ、ファイル名をオブジェクト名にしています。オブジェクト名に日本語が含まれている場合に対応するため、ファイル名のエンコードをUTL_URL.ESCAPEファンクションで実施しています。更新では、オブジェクト名の変更のみが可能です。オブジェクトの削除も実装しています。

ページ・デザイナオブジェクト一覧のページを開きます。

ボタンCREATEのクリックの際に、バケット名がフォームに渡されるようにターゲットの設定を変更します。


アイテムの設定に、名前P5_BUCKET_NAME、値&P4_BUCKET_NAME.とした行を追加します。

OKをクリックし、保存します。


これでファイルをオブジェクト・ストレージにアップロードする部分の実装はできました。ページを実行して、ファイルをアップロードしてみます。

ファイルを選択し、作成をクリックします。


ファイルがアップロードされたことが確認できます。


変更と削除についても、ターゲットの設定にバケット名を追加する必要があります。オブジェクト一覧のページをページ・デザイナで開き、対話モード・レポートの属性に含まれるリンクターゲットを開きます。


アイテムの設定に先ほどと同様に、名前P5_BUCKET_NAME&P4_BUCKET_NAME.の行を加えます。

OKをクリックします。


以上で削除変更の適用も実装ができました。

先程アップロードしたファイルを削除してみます。


この削除処理を実行しますか。と表示されるのでOKをクリックします。


オブジェクトが削除されたことが確認できます。


これからオブジェクトのダウンロードを実装するので、ファイルをひとつアップロードしておきましょう。

続く