ラベル APEX_APP_OBJECT_DEPENDENCY の投稿を表示しています。 すべての投稿を表示
ラベル APEX_APP_OBJECT_DEPENDENCY の投稿を表示しています。 すべての投稿を表示

2025年1月30日木曜日

APEX 24.2にデータベース・オブジェクトの依存性を確認するUIが追加されました

Oracle APEX 24.1でパッケージAPEX_APP_OBJECT_DEPENDENCYが追加され、APEXアプリケーションが依存しているデータベース・オブジェクトについて確認できるようになりました。APEX 24.2では、データベース・オブジェクトの依存性を確認するユーザー・インターフェースが、アプリケーション・ビルダーに追加されました。

以下の手順で呼び出します。

アプリケーション・ビルダーより、データベース・オブジェクトの依存性を確認する対象のアプリケーションを開きます。


ユーティリティを開きます。


データベース・オブジェクトの依存性を開きます。


依存性のスキャンが未実施のときは、アプリケーションのスキャンを実行するように促されます。アプリケーションのスキャンとは、APEX_APP_OBJECT_DEPENDENCY.SCANの実行です。


スキャン・タイプ有効範囲を設定し、スキャンを実行します。

スキャン・タイプの選択はFull ScanErrors onlyのどちらかです。APEX_APP_OBJECT_DEPENDENCY.SCANの引数p_optionsにあたる設定です。

Full Scanがc_option_all、Errors onlyがc_option_errorsになるようです。c_option_dependenciesおよびc_option_identifiersの切り替えが意味を持つのは、PL/Scopeとしてidentifiers:allを設定し、データベース・オブジェクトの再コンパイルを行った場合に限られます。

有効範囲を設定することで、特定のページのみをスキャンの対象にできます。


スキャンが完了すると、そのアプリケーションが依存しているデータベース・オブジェクトと、そのデータベース・オブジェクトを参照しているアプリケーション内の位置が表示されます。

左ペインのツリーには概ねビューAPEX_USED_DB_OBJECTSの内容が表示されています。左ペインでオブジェクトを選択すると、選択したデータベース・オブジェクトでビューAPEX_USED_DB_OBJ_DEPENDENCIESを絞り込んだ内容が一覧されます。


依存性のクリアをクリックすると、APEX_APP_OBJECT_DEPENDENCY.CLEAR_CACHEが呼び出されます。


コンポーネントのプロパティはリンクになっています。


クリックすると、アプリケーション・ビルダーの該当ページが開きます。


以上がAPEX 24.2で追加された、データベース・オブジェクトの依存性を確認するUIです。

APEX 24.2では、依存性を検出するカバレッジが広がりました。パッケージTESTを作成し、引数として与えられた文字列をそのまま返すファンクションECHOを作成します。
create or replace package test as
function echo(p in varchar2)
return varchar2;
end;
/
create or replace package body test as
function echo(p in varchar2)
return varchar2
as
begin
    return p;
end echo;
end test;
/
このTEST.ECHOを、追加された検出対象に含めます。

レポート列のSQL式が対象になります。


RESTソースのデータ・プロファイル列タイプSQL式が対象になります。


RESTソースのローカル後処理タイプSQL問合せが対象になります。


ユーティリティからデータベース・オブジェクトの依存性を開きます。

依存しているオブジェクトとして検出されたパッケージTESTを選択すると、上記の3箇所がコンポーネントのプロパティにリンクとして表示されます。


パッケージAPEX_APP_OBJECT_DEPENDENCYについては、以前の記事「APEX_APP_OBJECT_DEPENDENCYを使ってAPEXアプリケーションが参照しているデータベース・オブジェクトを確認する」で紹介しています。この記事で作成したアプリケーションをAPEX 24.2向けに修正しました。
https://github.com/ujnak/apexapps/blob/master/exports/application-object-dependency-scanner-242.zip

APEXの標準としてデータベース・オブジェクトの依存性を確認するページが追加されましたが、上記のAPEXアプリケーションは、APIの呼び出しやPL/Scopeの設定が含まれているので、まだ参考になる部分はあります。

なぜかAPEX 24.2では、ビューAPEX_USED_DB_OBJECT_COMP_PROPSより列COMPONENT_IDが除かれています。

この列が無くなって困ることは無いと思いますが、このビューをソースとしているレポートでエラーは発生する可能性はあります。その場合は、レポートの列を同期化することで対応できます。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2024年10月11日金曜日

APEX_APP_OBJECT_DEPENDENCYを使ってAPEXアプリケーションが参照しているデータベース・オブジェクトを確認する

Oracle APEX 24.1から新たにパッケージAPEX_APP_OBJECT_DEPENDENCYが追加されています。このパッケージに含まれているプロシージャSCANを呼び出すことで、APEXアプリケーションから参照されているデータベース・オブジェクトを確認することができます。

解析したいアプリケーションを選び、プロシージャAPEX_APP_OBJECT_DEPENDENCY.SCANを呼び出して、結果を確認するアプリケーションを作成してみました。SCANの結果は、ビューAPEX_USED_DB_OBJECT_COMP_PROPS、APEX_USED_DB_OBJECTSおよびAPEX_USED_DB_OBJ_DEPENDENCIESに保存されます。


ビューAPEX_USED_DB_OBJECT_COMP_PROPSは、解析対象のAPEXアプリケーションに設定されているデータベース・オブジェクト、SQLおよびPL/SQLコードを記録します。

ビューAPEX_USED_DB_OBJ_DEPENDENCIESは、APEX_USED_DB_OBJECT_COMP_PROPSとして取り出されたオブジェクトやコードが参照しているデータベース・オブジェクトを記録します。

ビューAPEX_USED_DB_OBJECTSは、ビューAPEX_USED_DB_OBJ_DEPENDENCIESの内容より、解析対象のAPEXアプリケーションが参照しているデータベース・オブジェクトを重複なしで記録します。

作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/application-object-dependency-scanner.zip

以降より、APEXアプリケーションの作成方法について簡単に紹介します。

最初に空のアプリケーションを作成します。名前Application Object Dependency Scannerとします。

アプリケーションの作成をクリックします。


アプリケーションが作成されます。パッケージAPEX_APP_OBJECT_DEPENDENCYを呼び出す処理は、すべてホーム・ページに実装します。


解析対象となるAPEXアプリケーションを選択するページ・アイテムP1_APPLICATIONを作成します。識別タイプは、APEX 24.1の新機能である1つ選択とします。ラベルApplicationとしています。

LOVタイプとしてSQL問合せを選択し、SQL問合せとして以下を記述します。

サインインしているワークスペースに含まれるAPEXアプリケーションの、どれかを解析対象として選びます。
select application_name d, application_id r from apex_applications where workspace_id = :WORKSPACE_ID


パッケージAPEX_APP_OBJECT_DEPENDENCYSCANCLEAR_CACHEを呼び出すボタンを作成します。また、CLEAR_CACHE_ALLとして、すべてのアプリケーションの解析結果を消去するボタンも作成します。

ボタンSCANについてはホットオンにします。すべてのボタンについて、外観テンプレート・オプションWidthStretchとし、ボタンの幅が画面に対して均等になるようにします。ボタンCLEAR_CACHECLEAR_CACHE_ALLについては、レイアウト新規行の開始オフにし、すべてのボタンを横一列に並べます。

動作アクションとしてページの送信を選択し、データベースの処理はページ・プロセスとして実装します。


ボタンCLEAR_CACHE_ALLは、動作確認の要求オンにして、確認メッセージとして本当に削除しますか?を設定します。スタイル危険を選択し、アプリケーションの解析結果を間違ってクリアしないようにします。


APEX_APP_OBJECT_DEPENDENCY.SCANの処理は、比較的時間がかかります。今回は、SCAN処理はバックグラウンドで実行することにします。

SCANを開始したバッググラウンド処理の実行IDを保存するページ・アイテムP1_EXECUTION_IDを作成します。識別タイプ非表示です。


バックグラウンド・プロセスの状態を表示するリージョンを作成します。

識別名前Scan Processタイプクラシック・レポートとします。ソース表名にバックグラウンド処理のステータスを保持するビューAPEX_APPL_PAGE_BG_PROC_STATUSを設定し、WHERE句execution_id = :P1_EXECUTION_IDを設定します。表示するバックグラウンド処理は、直近のSCANボタンのクリックで開始したバックグラウンド・プロセスに限定します。

外観テンプレートBlank with Attributesとします。

レポートのから、あまり参照する必要のない、WORKSPACEWORKSPACE_DISPLAY_NAMEAPPLICATION_IDAPPLICATION_NAMEWORKING_COPY_NAMEPAGE_IDPAGE_NAMESERIAL_EXECUTIONCURRENT_PROCESS_IDCURRENT_PROCESS_NAMECURRENT_PROCESS_SEQUENCEPROCESS_TYPE_PLUGIN_NAMEコメント・アウトします。


SCANの結果を表示するビューは対話モード・レポートで表示します。それぞれのビューをソースとした対話モード・レポートを、切り替えて表示できるようにリージョン表示セレクタを作成します。

識別名前Region Selectorタイプとしてリージョン表示セレクタを選択します。外観テンプレートBlank with Attributesを選択します。


ビューAPEX_USED_DB_OBJECT_COMP_PROPSAPEX_USED_DB_OBJ_DEPENDENCIESおよびAPEX_USED_DB_OBJECTSソースとした対話モード・レポートのリージョンを作成します。

リージョンのソース表名にそれぞれのビュー名を設定し、識別名前ソースとなるビュー名を設定します。ソースWHERE句application_id = :P1_APPLICATIONを設定し、直近の解析対象としたアプリケーションに限定して、依存関係を表示します。

関連した複数のアプリケーションが参照しているデータベース・オブジェクトを表示したい場合は、このWHERE句の条件は不要になります。

詳細リージョン表示セレクタオンにし、表示されるレポートをリージョン表示セレクタによる切り替えの対象にします。


以上で、画面については完成です。

続いて、ボタンSCANCLEAR_CACHECLEAR_CACHE_ALLをクリックしたときに実行されるプロセスを作成します。

SCAN処理をバックグラウンドで実行するために、実行チェーンを作成します。

プロセスを作成し、識別名前Background SCANタイプ実行チェーンとします。設定実行限度即時に送信オンバックグラウンドで実行オンにします。IDをアイテムに戻すP1_EXECUTION_IDを指定します。

シリアライズオフにします。実行限度なので、同時に実行できるバックグランド・プロセスは1つだけ、また、すでに実行しているバックグラウンド・プロセスがある場合は、待機せずにエラーになります。

サーバー側の条件ボタン押下時SCANを指定します。


実行チェーンBackground SCANに子プロセスを作成します。

識別名前Scanタイプコードを実行実行チェーンBackground SCANです。ソースPL/SQLコードとして以下を記述します。

apex_app_object_dependency.scan(:P1_APPLICATION);


アプリケーションごとにキャッシュをクリアするプロセスを作成します。

識別名前Clear Cacheタイプコードを実行です。ソースPL/SQLコードとして以下を記述します。

apex_app_object_dependency.clear_cache(:P1_APPLICATION);

サーバー側の条件ボタン押下時CLEAR_CACHEを指定します。


キャッシュされているすべてのアプリケーションの情報をクリアするプロセスを作成します。

識別名前Clear Cache ALLタイプコードを実行です。ソースPL/SQLコードとして以下を記述します。
begin
    for c in (select application_id from apex_applications where workspace_id = :WORKSPACE_ID)
    loop
        apex_app_object_dependency.clear_cache(c.application_id);
    end loop;
end;
サーバー側の条件ボタン押下時CLEAR_CACHE_ALLを指定します。


今までの作業で、APEX_APP_OBJECT_DEPENCENCYを使ってAPEXアプリケーションが参照しているデータベース・オブジェクトを確認する実装は完成です。

APIリファレンスのSCANプロシージャに、PL/Scopeの説明があります。

APEXアプリケーションが参照しているPL/SQLパッケージがPL/Scopeを有効にしてコンパイルされていると、APEX_APP_OBJECT_DEPENCENCY.SCANの結果に、APEXアプリケーションが呼び出しているパッケージ名の他に、プロシージャやファンクションも依存関係に含まれるようになります。

APIリファレンスには、PL/Scopeを有効にしてパッケージをコンパイルするコードとして、以下が記載されています。
alter session set plscope_settings='identifiers:all';
exec sys.dbms_utility.compile_schema(user, true);
alter session set plscope_settings='identifiers:none';
依存関係の確認は開発環境で実施し、本番環境では行わないことが推奨されています。そのため、PL/Scopeの設定としてidentifiers:allを設定し、スキーマをすべて再コンパイルしています。

今回作成するアプリケーションは機能の確認を目的としているため、もう少し細かい単位でPL/Scopeを有効化できるようにします。

パッケージを対話モード・レポートに一覧し、パッケージごとにPL/Scopeを有効にして再コンパイルするページを作成します。

ページ作成ウィザードより、対話モード・レポートの作成を呼び出します。

ページ番号名前Packagesフォーム・ページを含めるオンにします。フォーム・ページ番号フォーム・ページ名PL/Scopeとします。

データ・ソースSQL SELECT文を入力として以下を記述します。

select * from all_plsql_object_settings where type = 'PACKAGE'

フォームのページでは、オブジェクトの作成や更新ではなく、パッケージの再コンパイルを実装します。

へ進みます。


主キー列1OWNER (Varchar2)主キー列2Name (Varchar2)を選択します。

ページの作成をクリックします。


対話モード・レポートとフォームのページが作成されます。

対話モード・レポートのページを開き、列OWNERNAMEタイプを非表示からプレーン・テキストに変更します。主キー列として選択された列は、レポートの表示対象から外されています。

ボタンCREATEは不要なので、コメント・アウトします。


フォームのページを開き、ボタンSAVEラベル有効化に変更します。


ボタンDELETEのラベルを無効化に変更します。


ページ・アイテムP3_OWNERタイプ表示のみに変更します。ラベルOwnerとします。


ページ・アイテムP3_NAMEタイプ表示のみに変更します。ラベルNameとします。


左ペインでプロセス・ビューを開き、PL/Scopeを設定して再コンパイルするプロセスを作成します。デフォルトで作成されているプロセス・フォームPL/Scopeコメント・アウトします。

PL/Scopeの設定をIDENTIFIERS:ALLとして再コンパイルするプロセスを作成します。

識別名前Enableとします。タイプコードを実行ソースPL/SQLコードとして以下を記述します。
execute immediate 'ALTER SESSION SET PLSCOPE_SETTINGS=''IDENTIFIERS:ALL''';
execute immediate 'alter package ' || :P3_OWNER || '.' || :P3_NAME || ' compile package';
execute immediate 'ALTER SESSION SET PLSCOPE_SETTINGS=''IDENTIFIERS:NONE''';
サーバー側の条件ボタン押下時SAVEを指定します。


PL/Scopeを無効にするプロセスを作成します。

識別名前Disableとします。タイプコードを実行ソースPL/SQLコードとして以下を記述します。
execute immediate 'ALTER SESSION SET PLSCOPE_SETTINGS=''IDENTIFIERS:NONE''';
execute immediate 'alter package ' || :P3_OWNER || '.' || :P3_NAME || ' compile package';
サーバー側の条件ボタン押下時DELETEを指定します。


以上でパッケージの状態を確認して、PL/Scopeを有効/無効にして再コンパイルするページが追加できました。

ギャラリスターター・アプリケーションに含まれるCustomersをインストールして、今までの実装を確認してみます。

アプリケーションを実行し、ホーム・ページを開きます。最初にClear Cache ALLを実行します。


Packagesのページを開き、列Ownerワークスペース・スキーマで絞り込みます。ワークスペースにあるPL/SQLパッケージのPL/Scopeの設定(列Plscope Settings)がIDENTIFIERS:NONEであることを確認します。スターター・アプリケーションのCustomersは、パッケージEBA_CUSTEBA_CUST_EMAILEBA_CUST_FWEBA_CUST_SAMPLE_DATAを参照しています。

ホーム・ページに戻って、ApplicationCustomersを選択してSCANを実行します。

Status CodeENQUEUEDEXECUTINGと遷移し、最終的に(処理が成功すれば)SUCCESSに変わります。

ページを手動で再ロードして、現在のステータスを確認します。


SCAN処理が完了すると、それぞれのビューにAPEXアプリケーションを解析した情報が表示されます。


APEX_USED_DB_OBJECTSのリージョンを表示し、Referenced Ownerワークスペース・スキーマReferenced TypePACKAGEを選択し、APEXアプリケーションCustomersが呼び出しているPL/SQLパッケージを確認します。


また、Referenced TypeMETHODが含まれていないことを確認します。


Packagesの一覧を開き、パッケージEBA_CUSTEBA_CUST_EMAILEBA_CUST_FWEBA_CUST_SAMPLE_DATAのフォームを開いて、有効化を実行します。


パッケージのPlscope SettingsIDENTIFIERS:ALLに変更されたことを、レポートから確認します。


ホーム・ページに戻り、再度Scanを実行します。

APEXアプリケーションが参照しているパッケージがIDENTIFIERS:ALLでコンパイルされているため、Referenced TypeMETHODが現れ、Referenced Nameパッケージ名Referenced Sub Nameプロシージャ名またはファンクション名が表示されます。


最後にAPEXアプリケーションが参照しているデータベース・オブジェクトから、ビューALL_DEPENDENCIESを検索するページを追加します。

ページ作成ウィザードを呼び出し対話モード・レポートを選択します。

ページ番号4名前all_dependenciesとします。データ・ソースソース・タイプSQL問合せを選択し、SQL SELECT文を入力に以下を記述します。
select * from all_dependencies where (owner, type, name) in (select referenced_owner owner, referenced_type type, referenced_name name from apex_used_db_objects)
以上でページの作成を実行します。


APEX_APP_OBJECT_DEPENDENCY.SCANにより検出したデータベース・オブジェクトが参照しているデータベース・オブジェクトを、ビューALL_DEPENDENCIESより確認することができます。


以上ではアプリケーションは完成です。

APIリファレンスにKnown Limitationsとして制限事項が記載されています。検出対象外の設定もいくつかあるようです。ビューAPEX_USED_DB_OBJECTSだけでなく、ビューAPEX_USED_DB_OBJECT_COMP_PROPSやAPEX_USED_DB_OBJ_DEPENDENCIESも確認することにより、検出対象となっていない設定を確認することができます。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。