2024年9月30日月曜日

コマンドラインからAPEXのPL/SQL APIを呼び出すスクリプトの実行時トレースを取得する

Oracle APEXのPL/SQL APIを呼び出すスクリプトの実行時トレースを、画面に表示する方法を紹介します。

APEXのPL/SQL APIを含むスクリプトとして、APEXアプリケーションのインストール・スクリプトを例として使用します。

空のAPEXアプリケーションを作成します。空のAPEXアプリケーションのエクスポートだと、これといった実行時トレースが生成されないため、サポートするオブジェクトとしてインストール・スクリプトを作成します。

サポートするオブジェクトを開きます。


インストールするスクリプトを作成します。


作成をクリックします。


簡単なテストを作るだけなので、最初から作成を選びます。


名前testとし、エディタの使用チェックを入れます。

へ進みます。


スクリプト・エディタが開きます。以下の簡単なSQLスクリプトを記述します。
declare
    l_empno emp.empno%type;
begin
    select empno into l_empno from emp where ename = 'SCOTT';
end;
作成をクリックします。


インストール・スクリプトが作成されました。


アプリケーションをエクスポートします。エクスポート/インポートを開きます。


タスクのエクスポートを開きます。


サポートするオブジェクトの定義はい、または、インポート時に自動的にインストールを選択し、SQLファイルとしてエクスポートするために複数のファイルに分割オフにします。


以上でAPEXアプリケーションがf<アプリケーションID>.sqlというファイル名でエクスポートされます。

APEXアプリケーションのインストール手順については、以前の記事「コマンドラインからアプリケーションをインポートする」で紹介しています。以下では、APEXワークスペースのデフォルト・パーシング・スキーマにSQLclで接続した状態を前提とします。

実行時トレースを画面に出力するために、APEX_DEBUG.ENABLE_DBMS_OUTPUTを呼び出します。DBMS_OUTPUTの出力を画面に表示するため、set serveroutput on size unlimitedの実行も必要です。また、ログ・レベルによりますが大量のログが出力されるため、spoolコマンドを実行しファイルにも出力するようにします。

デバッグ出力を有効にするためAPEX_DEBUG.ENABLEを呼び出します。以下ではレベルとして最も詳細なc_log_level_engine_traceを指定していますが、最初はc_log_level_infoを設定して動作を確認する方が良いと思います。設定可能なレベルは、パッケージAPEX_DEBUGのConstantsに説明されています。

インストール・スクリプトを実行するために、APEX_APPLICATION_INSTALL.SET_AUTO_INSTALL_SUP_OBJを呼び出しています。
set serveroutput on size unlimited
spool install.log
begin
    apex_application_install.set_auto_install_sup_obj( p_auto_install_sup_obj => true );
    apex_debug.enable_dbms_output(p_prefix=>'DebugInstall##-');
    apex_debug.enable(p_level => apex_debug.c_log_level_engine_trace);
end;
/
必要に応じて、パッケージAPEX_APPLICATION_INSTALLの他のAPIの呼び出しも追加します。

実行例は以下になります。エクスポートしたAPEXアプリケーションのIDは181です。

SQL> set serveroutput on size unlimited

SQL> spool install.log

SQL> begin

     apex_application_install.set_auto_install_sup_obj( p_auto_install_sup_obj => true );

     apex_debug.enable_dbms_output(p_prefix=>'DebugInstall##-');

     apex_debug.enable(p_level => apex_debug.c_log_level_engine_trace);

     end;

     /


PL/SQLプロシージャが正常に完了しました。


SQL> @f181



APEXアプリケーションのインポートスクリプトが開始すると、以下のようにログが大量に出力されます。実行時トレースの出力にはDebugInstall##--がプレフィックスとして付加されています。

--application/set_environment

DebugInstall##--8-|init cgi_var_name.count=>0                                                      

%CGI.init:723<-%CGI.__pkg_init:869<-%SECURITY.get_ecid:4753<-%DEBUG.log_session_info:1140<-%DEBUG.log_message_int

DebugInstall##-                                                                                     ernal:1240<-%DEBUG.enter:483<-%IMP.import_begin:884<-:2

DebugInstall##----|State is now App=, Page=, Session=0, Workspace=0, User=

------------------------------------------------------------------------------------------------------------------------------------------

DebugInstall##-INF|ECID not set via CGI header, fetching from v$session                            

%SECURITY.get_ecid:4756<-%DEBUG.log_session_info:1140<-%DEBUG.log_message_internal:1240<-%DEBUG.enter:483<-%IMP.i

DebugInstall##-                                                                                     mport_begin:884<-:2

DebugInstall##-INF|ECID not set via v$session, generating with sys_guid()                          

%SECURITY.get_ecid:4766<-%DEBUG.log_session_info:1140<-%DEBUG.log_message_internal:1240<-%DEBUG.enter:483<-%IMP.i

DebugInstall##-                                                                                     mport_begin:884<-:2

DebugInstall##--9-|APEX Version=24.1.1                                                              %IMP.import_begin:884<-:2

DebugInstall##-   |Patch Version=1

DebugInstall##-   |SID=13401

DebugInstall##-   |USER=WKSP_APEXDEV

DebugInstall##-   |ECID=23516A574E408F58E063F15C000A482F

DebugInstall##-   |INSTANCE=4

DebugInstall##-   |

DebugInstall##--9-|R E Q U E S T SQLcle/

DebugInstall##--8-|import_begin

p_version_yyyy_mm_dd=>2024.05.31,p_release=>24.1.1,p_default_workspace_id=>7582124972789269,p_default_application_id=>181,p_default_id_offset=>67131626877163238,p_default_own

er=>WKSP_APEXDEV

DebugInstall##--8-|component_begin

p_version_yyyy_mm_dd=>2024.05.31,p_release=>24.1.1,p_default_workspace_id=>7582124972789269,p_default_application_id=>181,p_default_id_offset=>67131626877163238,p_default_own

er=>WKSP_APEXDEV

DebugInstall##-                                                                                     %IMP.component_begin:727<-%IMP.import_begin:898<-:2

DebugInstall##--8-|get_owner_of_calling_code callstack=>----- PL/SQL Call Stack -----              

%SECURITY.get_owner_of_calling_code:4571<-%IMP.component_begin:770<-%IMP.import_begin:898<-:2

DebugInstall##-   |  object      line  object

DebugInstall##-   |  handle    number  name

DebugInstall##-   |0xbc88946a8      4571  package body APEX_240100.WWV_FLOW_SECURITY.GET_OWNER_OF_CALLING_CODE

DebugInstall##-   |0x275b4cd68       770  package body APEX_240100.WWV_FLOW_IMP.COMPONENT_BEGIN

DebugInstall##-   |0x275b4cd68       898  package body APEX_240100.WWV_FLOW_IMP.IMPORT_BEGIN

DebugInstall##-   |0xa7c6feda0         2  anonymous block

DebugInstall##-   |

DebugInstall##----|State is now App=181, Page=, Session=0, Workspace=0, User=

---------------------------------------------------------------------------------------------------------------------------------------

DebugInstall##--9-|...skip APEX_240100.WWV_FLOW_SECURITY, APEX code                                

%SECURITY.get_owner_of_calling_code:4577<-%IMP.component_begin:770<-%IMP.import_begin:898<-:2


サポート・オブジェクトインストール・スクリプトは、インストール・スクリプトの最後に実行されます。

DebugInstall##-                                                                                    

_WIZARD.run_stmt:261<-%INSTALL_WIZARD.run_script:352<-%INSTALL_WIZARD.install:611<-%INSTALL_WIZARD.auto_install_s

DebugInstall##-                                                                                    

up_obj:1143<-%IMP.post_import_process:1279<-%IMP.component_end:1296<-%IMP.import_end:1336<-:2

DebugInstall##-   |

DebugInstall##-   |    l_empno emp.empno%type;

DebugInstall##-   |

DebugInstall##-   |begin

DebugInstall##-   |

DebugInstall##-   |    select empno into l_empno from emp where ename = 'SCOTT';

DebugInstall##-   |

DebugInstall##-   |end;,p_language=>PLSQL

DebugInstall##--8-|enable_access old g_disabled_level=>2                                           

%SESSION_STATE.enable_access:155<-%SW_API.run_sql_arr:1225<-%SW_API.run_sql:1475<-%INSTALL_WIZARD.run_statement:2

DebugInstall##-                                                                                    

06<-%INSTALL_WIZARD.run_stmt:261<-%INSTALL_WIZARD.run_script:352<-%INSTALL_WIZARD.install:611<-%INSTALL_WIZARD.au

DebugInstall##-                                                                                    

to_install_sup_obj:1143<-%IMP.post_import_process:1279<-%IMP.component_end:1296<-%IMP.import_end:1336<-:2

DebugInstall##--8-|enable_access old g_disabled_level=>1                                           

%SESSION_STATE.enable_access:155<-%INSTALL_WIZARD.run_script:366<-%INSTALL_WIZARD.install:611<-%INSTALL_WIZARD.au

DebugInstall##-                                                                                    

to_install_sup_obj:1143<-%IMP.post_import_process:1279<-%IMP.component_end:1296<-%IMP.import_end:1336<-:2

...Completed supporting objects install

DebugInstall##--8-|write_credential_collection                                                     

WWV_IMP_UTIL.write_credential_collection:832<-%IMP.component_end:1300<-%IMP.import_end:1336<-:2

DebugInstall##--8-|write_remoteserver_collection                                                   

WWV_IMP_UTIL.write_remoteserver_collection:893<-%IMP.component_end:1301<-%IMP.import_end:1336<-:2

... elapsed: 146.37 sec


...done

SQL> 


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

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

2024年9月13日金曜日

PPTXjsおよびmammoth.jsを使ってPowerPointとWordのファイルをブラウザ上で表示する

PPTXjsmammoth.jsを使って、データベースのBLOBに保存されたMicrosoft PowerPoint(.pptx)とWord(.docx)をブラウザ上に表示してみます。

PPTXjsの場合は、読みやすく表示されるPowerPointもあれば、


背景色やフォントの色が適切に変換されず、まったく読めないスライドもあります。


日本語でのPPTXjsの利用実績を見つけることはできませんでした。これをそのままで使うのは難しいと思います。また、slideModeはdivs2slidesjsおよびrevealjsともに動作しませんでした。PPTXjsのデモのページでも動作していないため、APEXへの組み込み方に問題があるわけでも無さそうです。

とはいえ、PowerPointをブラウザ上でHTMLに変換して表示するJavaScriptライブラリは、ほとんど無いようです。どのようなものか、動作を確認してみる価値はあります。

mammoth.jsを使ったWordの変換では、大体は読める形式でHTMLに変換してくれる感じです。ただし、追加の実装をしないと埋め込まれた画像は表示されません。


以下より、APEXアプリケーションの作り方を紹介します。

PowerPointやWordのドキュメントをBLOBとして保存する表を作成します。

クイックSQLの以下のモデルから、表EBAJ_DOCV_DOCUMENTSを作成します。
# prefix: ebaj_docv
documents
    title vc80 /nn
    document file
レビューおよび実行をクリックします。


次のページでスクリプト名を入力し実行をクリックし、表示された確認画面で即時実行をクリックします。

EBAJ_DOCV_DOCUMENTSが作成されます。

続けて、アプリケーションの作成をクリックします。確認画面が表示されるので、再度アプリケーションの作成をクリックします。


アプリケーション作成ウィザードが起動します。表EBAJ_DOCV_DOCUMENTSソースとしたフォーム付き対話モード・レポートのページはあらかじめ追加されています。

ページの追加をクリックし、空白のページとしてWord ViewerPowerPoint Viewerさらにdownloadを追加します。

以上で、アプリケーションの作成を実行します。


アプリケーションが作成されたら、ファイルのアップロードとダウンロードの機能を調整します。ソースとなる表にBLOB列が含まれていると、アプリケーション作成ウィザードおよびページ作成ウィザードは、ファイルをBLOBにアップロードする機能と、BLOBをファイルとしてダウンロードする機能を自動的に作成してくれます。しかし、ファイル名列MIMEタイプ列は自動では設定されません。

ページ・デザイナで、ページ番号の対話モード・レポートのページを開きます。

DOCUMENTを選択し、BLOB属性MIMEタイプ列DOCUMENT_MIMETYPEファイル名列DOCUMENT_FILENAME最終更新列DOCUMENT_LASTUPD文字セット列DOCUMENT_CHARSETを設定します。

以上で変更を保存します。


ページ・デザイナで、ページ番号のフォームのページを開きます。

ページ・アイテムP3_DOCUMENTを選択し、ストレージMIMEタイプ列DOCUMENT_MIMETYPEファイル名列DOCUMENT_FILENAME文字セット列DOCUMENT_CHARSET、BLOB最終更新列DOCUMENT_LASTUPDを設定します。


以上で変更を保存します。

この時点でAPEXアプリケーションを実行し、確認に使用するPowerPointとWordのファイルをアップロードします。

表EBAJ_DOCV_DOCUMENTSの対話モード・レポートのページを開き、作成をクリックします。


ドロワーが開くので、適当にタイトルをつけてPowerPointやWordのファイルをアップロードします。


動作確認に使用するファイルを複数アップロードします。


続いて、JavaScriptのコード中よりURLを指定して、BLOBのデータを取り出せるようにします。

ページ・デザイナdownloadのページを開きます。

空白ページdownloadに、表EBAJ_DOCV_DOCUMENTSの主キーIDの値を渡して、BLOBをファイルとして返す機能を実装します。

ダウンロードするBLOBのIDを受け付けるページ・アイテムP6_IDを作成します。タイプ非表示セッション・ステートストレージリクエストごと(メモリーのみ)とします。


ページ・アイテムP6_IDに渡されたIDのBLOBを、ファイルとしてダウンロードするプロセスを作成します。識別タイプとしてAPEX 24.1で新設されたダウンロードを選択します。

設定ファイルの表示形式として添付を選択し、ソースSQL問合せとして、以下を記述します。

select document, document_filename from ebaj_docv_documents where id = :P6_ID


以上の設定を行うことにより、BLOBをファイルとして取得するURLをAPEX_PAGE.GET_URLにより生成できるようになりました。以下のように呼び出します。
declare
    l_url varchar2(400);
begin
    l_url := apex_page.get_url(
        p_application => :APP_ID
        ,p_page => 'download'
        ,p_items => 'P6_ID'
        ,p_values => :P4_ID -- assume select list on page 4
    );
    :P4_DOCUMENT_URL := l_url;
end;

最初にWord Viewerのページに、mammoth.jsを使ったWordビューワーを実装します。

ページ・デザイナWord Viewerのページを開きます。

ページ・プロパティHTMLヘッダーに、mammoth.jsをロードするためにimportmapを設定します。
<script type="importmap">
    {
        "imports": {
            "mammoth": "https://cdn.jsdelivr.net/npm/mammoth@1.8.0/+esm"
        }
    }
</script>

プレビューするドキュメントを選択するページ・アイテムとしてP4_IDを作成します。タイプ選択リストです。LOVタイプとしてSQL問合せSQL問合せとして以下を記述します。

select title d, id r from ebaj_docv_documents

追加値の表示オフNULL値の表示オンNULL表示値として- Select Document -を設定します。

以前の値を記憶するように、セッション・ステートストレージセッションごと(永続)とします。


ページを送信して選択したドキュメントをプレビューするボタンを作成します。

識別ボタン名VIEWラベルView動作アクションページの送信です。外観ホットオンテンプレート・オプションWidthStretchに設定します。


BLOBの取り出しに指定するURLを保持するページ・アイテムP4_DOCUMENT_URLを作成します。本来であればタイプ非表示とすべきですが、値を確認できるようにタイプテキスト・フィールドとします。セッション・ステートストレージセッションごと(永続)を選びます。


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

以下のPL/SQLコードを実行し、BLOBを取り出すURLをページ・アイテムP4_DOCUMENT_URLに設定します。
declare
    l_url varchar2(400);
begin
    l_url := apex_page.get_url(
        p_application => :APP_ID
        ,p_page => 'download'
        ,p_items => 'P6_ID'
        ,p_values => :P4_ID -- assume select list on page 4
    );
    :P4_DOCUMENT_URL := l_url;
end;
サーバー側の条件ボタン押下時VIEWです。


mammoth.jpを呼び出し、Wordドキュメントから生成したHTMLを表示します。

静的コンテンツのリージョンを作成し、以下のコードをソースHTMLコードに記述します。



以上で、Word Viewerは完成です。

アプリケーションは以下のGIF動画のように動作します。


次にPPTXjsを組み込んだPowerPoint Viewerを実装します。

GitHubのReleasesのページを開き、最新バージョンのv1.21.1(といっても2年以上前)のSource code (zip)をダウンロードします。PPTXjs-1.21.1.zipがダウンロードされます。

ダウンロードされたPPTXjs-1.21.1.zipを展開します。ディレクトリPPTXjs-1.21.1が作成され、その下にPowerPointをHTMLに変換するために必要なファイルが含まれます。

ディレクトリPPTXjs-1.21.1へ移動し、必要なファイルをpptxjs.zipにまとめます。

cd PPTXjs-1.21.1
zip -r pptxjs.zip js/d3.min.js js/dingbat.js js/divs2slides.js js/divs2slides.min.js js/filereader.js js/jszip.min.js js/nv.d3.min.js js/pptxjs.js js/pptxjs.min.js css/pptxjs.css css/nv.d3.min.css

% cd PPTXjs-1.21.1

 PPTXjs-1.21.1 % zip -r pptxjs.zip js/d3.min.js js/dingbat.js js/divs2slides.js js/divs2slides.min.js js/filereader.js js/jszip.min.js js/nv.d3.min.js js/pptxjs.js js/pptxjs.min.js css/pptxjs.css css/nv.d3.min.css

  adding: js/d3.min.js (deflated 65%)

  adding: js/dingbat.js (deflated 90%)

  adding: js/divs2slides.js (deflated 65%)

  adding: js/divs2slides.min.js (deflated 53%)

  adding: js/filereader.js (deflated 75%)

  adding: js/jszip.min.js (deflated 69%)

  adding: js/nv.d3.min.js (deflated 80%)

  adding: js/pptxjs.js (deflated 87%)

  adding: js/pptxjs.min.js (deflated 80%)

  adding: css/pptxjs.css (deflated 74%)

  adding: css/nv.d3.min.css (deflated 77%)

 PPTXjs-1.21.1 % 


共有コンポーネント静的アプリケーション・ファイルを開き、ファイルの作成をクリックします。


コンテンツに先ほど作成したpptxjs.zipを選択し、ファイルの解凍オンにします。

作成をクリックします。


ファイルが作成されたことを確認するため、静的アプリケーション・ファイルを開きます。


pptxjs.zipに固めたファイルが、静的アプリケーション・ファイルの一覧に含まれていれば準備は完了です。


ページ・デザイナPowerPoint Viewerのページを開きます。

ページ・アイテムP5_ID、ボタンVIEW、ページ・アイテムP5_DOCUMENT_URL、それと、プロセスGet Document URLは、Word Viewerと同様に作成します。ページ番号が5になっているため、その部分は変更します。

静的コンテンツのリージョンDocument ViewerHTMLコードは以下になります。

<div id="container" class="h600"></div>


ページ・プロパティJavaScriptファイルURLに以下を記述します。
#APP_FILES#js/jszip.min.js
#APP_FILES#js/filereader.js
#APP_FILES#js/d3.min.js
#APP_FILES#js/nv.d3.min.js
#APP_FILES#js/dingbat.js
#APP_FILES#js/pptxjs.min.js
#APP_FILES#js/divs2slides.min.js
CSSファイルURLに以下を記述します。
#APP_FILES#css/pptxjs.css
#APP_FILES#css/nv.d3.min.css
JavaScriptページ・ロード時に実行に以下を記述します。
$("#container").pptxToHtml({
    pptxFileUrl: apex.item("P5_DOCUMENT_URL").getValue(),
    slideMode: false,
    keyBoardShortCut: false
});

以上でPowerPoint Viewerは完成です。

アプリケーションは以下のGIF動画のように動作します。


今回の記事は以上です。

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

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