パーソナルツール
現在の場所: ホーム ブログ Categories dbMAGIC
« 2018January »
Su Mo Tu We Th Fr Sa
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
このBlogについて
 代表の向井田ことMUKAです。当ブログサイトでは、MAGICやDB2に関する技術者向け情報を公開しています。お気軽にお立ち寄り下さい。
最近のエントリ
twitter / 新RT機能を英語モードで・・・ muka 2009年11月19日
twitter / List Widget muka 2009年11月03日
twitter API / Retweet の仕様が・・・ muka 2009年10月30日
twitter API / Lists muka 2009年10月24日
IBM Rational Software Conference 2009 と アジャイル開発 muka 2009年10月08日
twitter API / geoタグ! muka 2009年10月01日
Twitter Developers Meetup in Tokyo muka 2009年09月11日
Club DB2 2009/9/4 muka 2009年09月05日
最近のコメント
Re:Club DB2 2009/8/29 muka 2009年09月01日
Re:Club DB2 2009/8/29 SIM 2009年08月31日
最近のトラックバック
Club DB2 8/29の感想エントリと今後の予定 Unofficial DB2 BLOG 2009年09月01日
カテゴリ
misc (47)
dbMAGIC (47)
DB2 (47)
mail (47)
Web (47)
twitter (47)
 

dbMAGIC

一つ上に移動
dbMAGIC ( MAGIC SOFTWARE JAPANの開発ツール ) に関する話題等

MAGIC + DB2 で XQuery(2)


データベースとテーブルの作成


 なんかもうすぐ春という季節になりましたが、如何お過ごしでしょうか?
 今日は確定申告の締切日でしたが、医療費控除の申告をようやくすませて、家内共々ほっとしているところです。なんかこの2・3年、ギリギリの日に提出することが続いています・・・(^^;

 さて、いきなり始まったDB2シリーズですが、今とあるシステムの試作にDB2 9を使って取り組んでいるんです。
 結構、試行錯誤の連続なんですね。でも、こういう風にブログに書き込むと、頭の中が整理されて良いものです。
 モノになるのかならないのかまだ分からないんですが、しばしお付き合い下さい。
 では、今回は、テーブルを作るところからです。

 データベースとテーブルの作成は、DB2の「コマンドウインドウ」(CLP-「コマンドラインプロセッサー」とも言う)を使って行い、その作成結果をMAGICの「定義取得」で行う手順について説明します。
 「コマンドウインドウ」はいわゆる「DOS窓」みたいなものですが(実際にDOSコマンドが入力できます。)、コマンドラインの先頭に「DB2」を付加することによりDB2に対するコマンド命令を操作することが可能です。

  1. インスタンスの起動
    インスタンスが起動していない場合は、「DB2START」コマンドによりそれを起動します。
    DB2START
  2. データベースの作成
    次のコマンドにより、「DB2XML」というデータベースを作成します。XMLタイプのカラムを使う場合は、コードセットをユニコードにします。
    CREATE DATABASE DB2XML ON C USING CODESET UTF-8 TERRITORY JP
  3. データベースへの接続
    作成したデータベースに接続します。DB2はログインしているユーザを認識するので、ユーザ名の指定は不要です。もし指定するなら、下記のコマンドの後に、「 user ユーザ名 using パスワード」を追加します。
    CONNECT TO DB2XML
  4. テーブルの作成
    次のコマンドにより、「XMLDBTEST」というテーブルを作成します。
    CREATE TABLE DB2ADMIN.XMLDBTEST(DATAID CHAR(20) NOT NULL,
    DATAXML XML,CONSTRAINT DATAID PRIMARY KEY(DATAID))
    ここで、テーブル名の先頭に付加している「DB2ADMIN」は「スキーマ」と呼ばれるものです。データベースオブジェクトを論理的にグループ化するためのものですが、何もつけない場合は、ユーザー名が付加されますので、敢えて固定的なものを指定しておいたほうが良いと思います。
    最初のカラムが「DATAID」という名前の文字タイプの項目です。二番目のカラムは「DATAXML」という名前の「XML」タイプ(DB2 9で新しく追加された型)の項目です。
    最初の「DATAID」というカラムはインデックスも作成しておきます。

  5. データベースへの接続の終了
    データベースへの接続を終了します。
    CONNECT RESET

 実際の実行画面は次のようになります。

v10db2_002.jpg


 今回は、コマンドウインドウで操作しましたが、「DB2CMD」という実行形式を使用し、テキストファイルにコマンドを書いて渡すことにより同様の処理が可能です。
 MAGICからは、外部コール、「OSコマンド」で、表示を「M=最小化」や「H=なし」を選択すれば殆ど分からなくなります。
DB2CMD /c /w /i DB2 -f 処理ファイル -zログファイル


MAGICでの定義取得


 MAGIC V10により、作成したテーブルを定義取得してみます。

  1. データベースの定義
    MAGIC V10を起動し、データベースの定義を実行します。(オプション→設定→データベース)
    DBMSに「DB2」を選択します。「DB名」には、作成したデータベース名「DB2XML」を設定します。(「DB名」には論理名も使用できるようです。)

    v10db2_001.jpg

  2. 定義取得
    データリポジトリを開き、定義を追加します。
    「データベース」には1で登録したDB2用のものを選択します。
    名前に「XMLDBTEST」を入れます。
    特性画面を開き(「Alt+Enter」)、「SQL」タブの「オーナ名」にテーブルを作成するときに指定したスキーマ名「DB2ADMIN」を入力します。(「オーナ名」にも論理名が使えるようです。)

    v10db2_003.jpg

    最後に「定義取得」を実行します。(「オプション」→「定義取得」、もしくは「F9」キー)
    しばらくすると処理が終了し、テーブルのカラムやインデックスが自動的に作成されます。

    v10db2_004.jpg

  3. カラム属性の修正
    自動的に作成されたカラム「DATAXML」は若干の修正が必要です。

    v10db2_005.jpg
    • 「型」を「A=文字」から「B=BLOB」に変更します。
    • 特性画面のSQLタイプを「XML」にします。(必須でないかもしれません。)
    • 特性画面のスタイルの「GUI表示形式」、「GUI表示形式テーブル」を「I=リッチエディット」等に変更します。(必須でないかもしれません。)

  4. テスト実行
    変更内容を保存して実行(「Ctrl+G」キー)してみてください。
    「DATAXML」カラムへは入力できませんが、「DATAID」に適当な文字を入力してみて、レコードの追加や削除ができればOKです。

    v10db2_006.jpg


MAGIC + DB2 で XQuery(1) MAGIC + DB2 で XQuery(1)
サイズ 4320 - File type text/html
カテゴリ
dbMAGIC
DB2

MAGIC + DB2 で XQuery(3)


インポート・ユーティリティ


 前回まででSQLデータベースに表ができたので、今回は実際にXMLファイルを取り込んでみます。

 まず、テーブルにレコードを挿入する方法ですが、次の2通りの方法があります。
 最初の方法は、SQL文の「insert」命令です。

insert into テーブル名 values(カラム1,カラム2,...,カラムN)

 しかし、XMLタイプの項目の場合、その内容を全て記述してあげないといけないのでちょっと大変です。

(例えば、

'<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Application>
<Header>
...略

</Application>'

のように・・・。)


 もう一つの方法は「importユーティリティ」を使うものです。
 こちらはファイルイメージのXMLファイルを、一括して取り込むことができるので、より便利な方法と言えるでしょう。

import from delファイル of del xml from XMLパス replace into テーブル名
 ここで、「delファイル」とあるのは、読み込みデータを記述した、いわゆるCSV形式ファイルです。このファイルは、各項目をカンマで区切って記述します。例えば、数値項目なら「100」、文字項目なら「"abc"」、XMLタイプの項目は、「"<xds fil='XMLファイル名' />"」のように記述します。
 このとき「XMLファイル名」にはパス名をつけなくて良く、ファイルの格納されたパスは上記のコマンドラインの「XMLパス」で指定します。(「delファイル」も、「XMLパス」もコマンドを実行しているディレクトリからの相対パスでもOK)

 「replace」は動作を表すオプションで、テーブル内のレコードは読み込む前に全てdropされます。残したまま追加読み込みさせたいなら「insert」を指定します。

 今回は、「MAGIC V10解析(8)」で作成したアプリケーションを改良し、プロジェクト・フォルダ内のプログラム・ソースを一括してインポートしてみます。


インポート用delファイル書き出しプログラム


 プロジェクトフォルダにデータ読み込み用の「inport_prg.del」というファイルを書き出すプログラムを作成してみます。
プログラムの一覧は、プロジェクトフォルダを自動的に検知し、メモリテーブルの「Progs.ProgNo」に作成されていますから、それをテキスト形式のファイルに書き出すだけです。
 プログラムの作成手順を下記に示します。

  1. プログラムの追加
    プログラムを追加して「delファイル出力」と名前をつけます。
    タスク特性は「B=バッチ」に指定します。
  2. データビュー
    メインソースは「4」の「Progs.ProgNo」を選択します。インデックスは何を選んでも構いませんが、表示順を見るために「2」の「ProgNo.」を選択します。
    カラムには、「1」の「id」を追加します。
    変数「出力イメージ」、文字タイプの書式「80」を追加します。代入に下記の式を追加します。プログラムのソースを表す「PRG」にidの5桁を加えたものを主項目にセットします。
    '"PRG'&Str(B,'5P0')&'","<xds fil=''Prg_'
    &Trim(Str(B,'5'))&'.xml'' />"'
  3. フォームの追加
    クラス1の「T=テキスト形式」フォームを追加します。幅「80.000」、高さ「1.000」とし、変数「出力イメージ」を配置します。
  4. 入出力ファイルの定義
    メディア:「F=ファイル」、アクセス:「W=書出」の名前「delファイル」を定義します。式には「'%Project%\inport_prg.del'」を指定します。
  5. ロジックの定義
    レコード後処理に、フォーム出力を定義します。


「プログラム一覧」からの起動メニューを組み込む


 ちょっと話題はズレますが、実は、前回ソース公開したプログラムには、プロジェクトフォルダを自由に選択できるような機能が組み込まれています。
 #2のプログラム「プログラム一覧」を単独で実行して頂くと、コンテキスト・メニューの「プロジェクトフォルダの選択」から、任意のフォルダを選択することのできるダイアログを起動します。

v10db2_015.jpg

 更に蛇足ですが、このフォルダ選択プログラム(#8「プロジェクトの選択(A)」)では、V10になって新しく実装された関数「DirDlg」を使用しています。
DirDlg ('プロジェクトの選択','プロジェクトフォルダを選択して下さい.',C,0)
 上記の式中、変数「C」には初期フォルダをセットしているのですが、前回ご紹介させて頂いた論理名「%WorkingDir%」を展開し、現在のプロジェクトフォルダを取得して初期値としています。

 さて、「プログラム一覧」のコンテキストメニューに、今回作成した「delファイル出力」を組み込んでみたいと思います。簡単な手順を示しておきます。

  1. メインプログラムへのイベント定義
    メインプログラムを開き、イベントテーブル(「Ctrl+U」キー)に「delファイル出力」を追加します。
  2. メニューの修正
    メニューリポジトリを開き、#3「プログラム一覧(有効プログラム)」と#4「プログラム一覧」にイベント「delファイル出力」を追加します。
  3. プログラム#2「プログラム一覧」の修正
    プログラム#2「プログラム一覧」を開き、タスク「2.1」を開きます。
    ロジックテーブルに、イベント「delファイル出力」を追加します。
    追加したイベントにコールプログラム#9と、OSコマンド「'notepad '&Translate('%Project%\inport_prg.del')」の定義を追加します。
  4. プログラムの実行
    プログラム#2「プログラム一覧」を実行します。
    コンテキストメニューから「プロジェクトフォルダの選択」を起動し、任意のプロジェクトフォルダを選択してみて下さい。(リスト内容が切り替わると思います。)
    更に、「delファイル出力」を実行します。メモ帳に出力されたdelファイルの内容が出力されます。


importユーティリティの実行

 
 さていよいよXMLデータベース(DB2 9)へのXMLのインポートです。
 とりあえず、今回もコマンドラインプロセッサーを使いましょう。
 スタートメニューから「コマンド・ウインドウ」を起動します。
 カレントディレクトリをリストを出力したプロジェクトフォルダに切り替え、下記のコマンドを入力してみて下さい。(大文字でも小文字でもOKです。)
IMPORT FROM INPORT_PRG.DEL OF DEL XML FROM SOURCE REPLACE
INTO DB2ADMIN.XMLDBTEST
v10db2_011.jpg


 このユーティリティですが、入力時には結構、厳しくXMLデータの内容のチェックをしているようで、XML中に使ってはいけないとされる半角カナなどの文字があると取り込みを拒否してしまいます。
(MAGICのソースはエラーとなるようなことはありません。)
 また、大規模なXMLファイルを読み込むような場合は、いろいろと注意が必要です。
 例えば、タグ内の文字列のサイズは最大で32000バイトです。これを超えるとこのタグの内容は検索することができなくなるので注意が必要です。複数のタグに分割する分にはOKです。
 他にも大量のレコード(何万件)を読み込む場合は幾分の設定の変更が必要になります。

 さて、読み込んだデータを確認してみましょう。
 MAGICでテーブルをAPGで開いてもそれなりの確認はできますが、ここではDB2のGUIユーティリティ「コントロールセンター」を使ってみます。起動すると下記のような画面が表示されます。

v10db2_012.jpg

 オブジェクトビューから作成した表「XMLDBTEST」を表示します。
 アクションから「オープン」すると内容の確認が可能です。

v10db2_013.jpg

 XMLの内容を見てみましょう。任意のレコードで「・・・」と書かれたボタンをクリックすると文書ビュアーが起動します。取り込まれたXMLドキュメントの内容の確認が可能です。

v10db2_014.jpg



 次回は、いよいよXMLデータベースの検索に挑戦です!

MAGIC + DB2 で XQuery(1) MAGIC + DB2 で XQuery(1)
サイズ 4320 - File type text/html
MAGIC + DB2 で XQuery(2) MAGIC + DB2 で XQuery(2)
サイズ 7143 - File type text/html
MAGIC V10解析(8) MAGIC V10解析(8)
サイズ 7011 - File type text/html
カテゴリ
dbMAGIC
DB2

MAGIC + DB2 で XQuery(4)


SQL/XML


 東京は桜も3分咲き程で、いよいよ春到来という感じですね。
 「春眠暁を覚えず」と言われますが、まさにそのとおりで、朝起きるのが辛いこの頃です。

 さて、前回まではXMLデータベースの作成手順まで説明してきました。いよいよ今回はXQueryを使った検索処理です。
 XQueryとは、XMLデータベース用のクエリー言語のことを言います。SQLデータベース用のクエリー言語がSQLであるのと同様に考えると分かり易いかもしれません。
 DB2 9は、XQueryをSQL言語でXMLを扱うための拡張仕様であるところの「SQL/XML標準」もサポートしており、これによってSQLからXQueryを実行することが可能です。
 つまり、同じ行(レコード)上のXML型の列のデータに対しては、SQL/XML関数を使うことができ、従来のSQLデータについてはSQLでクエリー処理を行うことができます。これが他のリレーショナルデータベースやXML専用データベースと異なる大きな点です。
 当然ながら、通常のカラムとXML型のカラムの両者を指定した複合的なクエリー処理を行うこともできるわけです。
 MAGIC V10でDB2 9を使用する場合は、このSQL/XMLを利用します。
 逆な言い方をすると、MAGICのいわゆる「SQLタイプ」のタスクで定義できるSQL文は、「SELECT文」(=SQL/XML)のみなので、この方法しかありません。例えば「FLWOR」形式を使用したxquery文等の処理ができるのかどうか試みたのですが、私が試した限りではエラーが出て使えませんでした。このあたりは、DB2のゲートウェイのバージョンアップに期待したいところです。
 そう言えば、書き忘れていたのですが、データベース特性のオプションにある「開発モードでのテーブル変換」ですが、これはチェックを外しておいてください。XMLタイプのカラムがあると変換に失敗してしまうので、テーブルの定義を変更するときなどは、現状は別個に修正する必要があります。


SELECT文の実際・・・


 例えば、コメントに「プログラム」 と記述されたプログラムの一覧を取得することを考えて見ましょう。コメントはプログラムにも、タスクにも、項目やフォームにもつけることが可能ですが、リポジトリ上は、「Comment」というタグの「val」属性に付きます。

プログラムに付いたコメントの場合は、XPATHで記述すると「/Application/ProgramsRepository/Programs/Task/Header/Comment」となりますが、そのサブタスクに付く場合は、「/Application/ProgramsRepository/Programs/Task/Task/Header/Comment」となります。更にそのサブタスク(孫タスク)の場合は、「/Application/ProgramsRepository/Programs/Task/Task/Task/Header/Comment」となるでしょう。
 プログラムやタスクではなく、例えば、あるイベントに付加されたコメントの場合はどうなるでしょうか? 答えは、「/Application/ProgramsRepository/Programs/Task/.../TaskLogic/LogicUnit/Comment」となります。
 MAGIC V10では、いろいろな場所にコメントを付けられますが、いずれの場合も「Comment」という名前のタグで検索することが可能です。
 どんな場所に付けられたコメントでも構わずに検索する場合は「/Application//Comment」と表すことが可能です。つまり「//」は間にどんなPATHが入ってもいいよという意味です。
 
 SELECT文は次のようになります。

select c.DATAID from DB2ADMIN.XMLDBTEST c where 
xmlexists('$i/Application[//Comment/@val[contains(.,"プログラム")]]'
passing c.DATAXML as "i")

 ちょっと複雑に見えるかもしれませんが、構文はお馴染みのSELECT文「SELECT ... FROM ... WHERE ... ORDER BY ... 」です。
 XMLEXISTS関数は、存在すればTrueを返すもので、WHERE句に使用することが可能です。
 「//Comment」で階層下の任意のコメントを表すことはすでに書いたとおりですが、プログラムのコメントのみを対象とするなら「/ProgramsRepository/Programs/Task/Header/Comment」とします。
 「[contains(.,"文字列")] 」は、「文字列」を含むという条件を意味します。
 もし、上記の検索に「かつ、ルートタスクがバッチタスクのプログラム」という条件を加えるなら次のようになります。("[" と "]" の中でAND条件を加えます。)

select c.DATAID from DB2ADMIN.XMLDBTEST c where 
xmlexists('$i/Application[//Comment/@val[contains(.,"プログラム")]
and /ProgramsRepository/Programs/Task/Header/TaskType/@val="B"]'
passing c.DATAXML as "i")

 さて、今度は返るデータについてみてみましょう。
 上の例では、該当レコードの「DATAID」カラムの一覧が返ります。
 例えば、ここに「xmlquery」関数を使用することにより、該当するXMLノードの結果をXMLで返すことも可能です。例えば、次のような例です。

select c.DATAID, xmlquery('$i/Application/ProgramsRepository
/Programs/Task/Header' passing c.DATAXML as "i")
from DB2ADMIN.XMLDBTEST c where
xmlexists('$i/Application[//Comment/@val[contains(.,"プログラム")]]'
passing c.DATAXML as "i")

 DATAIDに続いてカンマとxmlquery関数を使った項目が指定されています。



MAGIC V10でのコーディング


 実際にV10でコーディングしてみます。
 プログラムは2種類作ってみます。最初は、テスト用のプログラムです。

  1. プログラムの定義
    「SQL/XMLサンプル1」というプログラムを追加します。(タスクタイプはオンライン)
  2. データビューの定義
    メインソースなしで、変数を3つ定義します。
    1. 「SQL文」
      文字タイプ、書式512、代入で式「'select c.DATAID, xmlquery(''$i/Application/ProgramsRepository/Programs/Task/Header'' passing c.DATAXML as "i") from DB2ADMIN.XMLDBTEST c where xmlexists(''$i/Application[//Comment/@val[contains(.,"プログラム")]]'' passing c.DATAXML as "i")'」を定義します。
    2. 「出力XMLファイル」
      文字タイプ、書式256、代入で式「'C:\V10HACKS.XML'」を定義します。
    3. 「データ有り」
      論理タイプ、書式5
  3. ロジックの定義
    イベントテーブルに「処理実行」というユーザイベントを追加しておきます。
    イベントハンドラを定義し、コールサブタスク
    エラーで、'データが見つかりませんでした.'、条件は「NOT(データ有り)」
  4. フォームの定義
    SQL文を編集できるように「複数行編集」可能なエディットコントロールを配置します。
    ユーザイベント「処理実行」を実行するためのプッシュボタンを配置します。
  5. 子タスクの定義
    ロジックでコールした子タスクを作成します。(タスクタイプは同じくオンライン)
  6. データビューの定義(子タスク)
    変数を3つ追加します。
    1. DATAID
      文字タイプ、書式20、
    2. HEADER
      BLOBタイプ
    3. プログラムID
      数値タイプ、書式5、代入に式「Val(Del(DATAID,1,3),'5')」
    「M=メインソース」と表示されたコンボボックスを「Q=SQLコマンド」に変更します。

    v10db2_025.jpg

    TABキーを押して表示されるダイアログに下記のものをセットします。
    1. データベースは「DB2XML」を選択します。
    2. 結果データベースは「Memory」を選択します。
    3. SQLコマンドには、「:1」を入力します。
    4. 入力パラメータには、親タスクの「SQL文」項目を指定します。
    5. 出力パラメータは、追加した変数のDATAIDとHEADERを定義します。
    照会リンクを追加します。(データソース:XMLDBTEST)
    1. DATAID
      位置付けに変数「DATAID」を指定します。
    2. DATAXML
      XMLデータの格納されたカラムをリンクしておきます。
  7. ロジックの定義(子タスク)
    ユーザイベントを4つ(「ブラウザ(QUERY)」、「ブラウザ(DATAXML)」、「XML解読」、「タスク一覧」)追加しておきます。
    タスク前処理に親タスクの変数「データ有り」を'FALSE'LOGで更新を定義します。
    レコード前処理に親タスクの変数「データ有り」を'TRUE'LOGで更新を定義します。
    イベント「ブラウザ(QUERY)」にアクション「Blb2File (HEADER,出力XMLファイル)」と、OSコマンド「出力XMLファイル)」を定義します。
    イベント「ブラウザ(DATAXML)」にアクション「Blb2File (DATAXML,出力XMLファイル)」と、OSコマンド「出力XMLファイル)」を定義します。
    イベント「XML解読」に、コールサブタスクを定義します。
    イベント「タスク一覧」に、コールプログラム「タスク構造取得」を定義し、パラメータに「プログラムID」を指定します。更に、条件式「DbRecs ('5'DSOURCE,'')>0」なら、コールプログラム「タスク一覧表示」を定義します。
  8. フォームの定義(子タスク)
    テーブルコントロールに、変数「DATAID」、「プログラムID」、「HEADER」、リンク項目「DATAXML」を配置します。更に定義したイベントを起動するためのプッシュボタンを配置します。
  9. 孫タスクの定義
    取得したXML(HEADER)を解析する子タスクを追加します。
    詳細な説明は省略しますが、データビューに定義した変数に、XMLGET関数を使用して、親タスクの変数「HEADER」に格納された情報から、プログラム名、タスクタイプ、更新日付、更新時刻などの値をそれぞれ取得し画面に表示します。
    このとき、XPATHが、「/Header」で始まることに注目して下さい。

    変数名 値の取得方法(代入する式の値)
    プログラム名 XMLGet (0,1,'/Header','Description')
    タスクタイプ XMLGet (0,1,'/Header/TaskType','val')
    更新日付 Val(XMLGet (0,1,'/Header/LastModified','_date'),'10')
    更新時刻 Val(XMLGet (0,1,'/Header/LastModified','_time'),'10')


プログラムの実行


 作成したプログラムを実行してみましょう。
 
  1. プログラムの起動
    起動すると、ダイアログにSQL/XMLのSELECT文が表示されます(編集も可能です)。

    v10db2_021.jpg

    「SQLの実行」ボタンを押すと、DB2によるデータの検索が行われます。
  2. SQL/XML検索結果
    画面の例では、2件のプログラムが検索されました。

    v10db2_022.jpg

    DB2から返る値は、出力パラメータに指定した「DATAID」と「HEADER」ですが、プログラムのIDを判別し前回作成したタスク一覧プログラムを呼び出すことが可能です。また、BLOBに格納されたXMLデータは、いずれも「Blb2File」関数でXMLに出力することが可能です。(残念ながら、「File2Blb」関数を使って、XMLをXMLタイプのカラムに挿入することはできません。)
  3. xmlquery関数で取得したXMLデータ
    ブラウザにxmlquery関数で取得したXMLデータを表示させてみます。

    v10db2_023.jpg

    指定したパス以下の部分的なXMLデータが出力されることが分かります。
  4. MAGICでの解析
    DB2に格納されたXMLデータや、検索で取得したXMLデータは、MAGICのXML関連の関数によって任意のノードの値を取得することが可能です。BLOB項目を直接指定してXMLの値の取得が可能なので、不要なIOも発生しません。

    v10db2_024.jpg



ソース公開


 例によって、今回も作成したプログラムのソースを公開しておきます。







MAGIC + DB2 で XQuery(1) MAGIC + DB2 で XQuery(1)
サイズ 4320 - File type text/html
MAGIC + DB2 で XQuery(2) MAGIC + DB2 で XQuery(2)
サイズ 7143 - File type text/html
MAGIC + DB2 で XQuery(3) MAGIC + DB2 で XQuery(3)
サイズ 10488 - File type text/html
V10HACKS_20070329.lzh V10HACKS_20070329.lzh
サイズ 95.6 kB - File type application/x-lzh
カテゴリ
dbMAGIC
DB2

MAGIC + DB2 で XQuery(5)


クロスリファレンスに挑戦!


 前回は、SQL/XML機能を用いてMAGIC V10のプログラムリポジトリから任意の文字列検索を行ってみました。
 今回は、プログラムのクロスリファレンス検索を行ってみようと思います。
 クロスリファレンス機能は、オブジェクト(プログラム等)を参照している他のオブジェクト(プログラム等)を逆引きする機能ですが、MAGICの開発を行っている方にはお馴染みの機能かと思います。V9になってクロスリファレンスの結果が保存されるようになったので、とても便利になりましたよね。V10にも同様の機能が実装されています。

 さて、このリファレンスを検索するにはどうすればいいでしょうか?
 V10のプログラムとそのリポジトリファイルの内容を実際に見比べてみます。
 まず、プログラム編集画面ですが、適当なプログラムを開き、ロジックの一部分でプログラムをコールしている箇所を探します。(下図は、「受注登録(Single)」プログラムのロジックタブの画面)

v10db2_031.jpg


 次に、このプログラムのリポジトリ(XMLファイル)の該当箇所をXMLのソースから探します。下記の部分が該当箇所になります。


v10db2_032.jpg

 このことから類推すると、あるプログラム(id=X)を参照しているプログラムの一群は、

子ノード「OperationType/@val」の値が"P"であり、
かつ、子ノード「TaskID/@comp」の値が"-1"で、
かつ、子ノード「TaskID/@obj」の値がXである
「CallTask」ノードを持つXMLドキュメント(プログラム)

を条件に探せば良いということになりそうです。

 さて、上記の条件を xmlexists 関数に置き換えてみましょう。
 前回公開させて頂いたプログラムソースの12番「SQL/XMLサンプル2」プログラムに今回のプログラムは作成済みです。該当箇所(ルートタスクの式4)は次のように記述してあります。

'select c.DATAID from DB2ADMIN.XMLDBTEST c where
 xmlexists(''$i/Application//CallTask[OperationType/@val="P"
 and TaskID/@comp="-1" and TaskID/@obj="'&Trim(Str(B,'5'))&'" ]''
 passing c.DATAXML as "i")'

 このSQL/XML文を実行することにより、コールしているプログラムを検索することが可能です。
 簡単に、上記SELECT文の解説をしておきましょう。
 まず、「/Application//CallTask」と間に「//」を入れることにより、任意の階層のタスクの「CallTask」ノードが該当するようになります。
 「and」で連結する条件式は、"[" と "]" の間に記述するようにします。
 「Trim(Str(B,'5'))」は、プログラムのidですが、これはパラメータで任意のプログラムのリファレンスを検索できるようにするためのものです。
 「comp」属性は、コンポーネントを利用しているアプリケーションの場合は、そのコンポーネントの番号が記載されます。今回は、同じアプリケーション内のプログラム(-1の値が指定される)に限定して検索を行うことになります。(うまく処理できれば、コンポーネントを使用しているアプリケーション間のクロスリファレンスの取得も可能かもしれませんね!)

 さて、いよいよ、プログラムを実行してみましょう。


クロスリファレンスの実行


 今回作成したプログラムは、#2:「プログラム一覧」を実行し、プログラムを一覧表示させたときのポップアップメニューから実行できるようにしてあります。
 XMLファイル(プログラムのリポジトリ)をインポートしたプロジェクトを選択し、プログラムの一覧を表示します。

v10db2_033.jpg

 任意のプログラム(画面上は、「受注書印刷 BTCH」)をクリックし、マウスの右ボタンから、「SQLテスト2」を選択します。
 するとどうでしょうか?検索が終わり、下記のようにプログラムを参照しているプログラムの一覧が表示されます。

v10db2_034.jpg

 試しに、MAGIC V10のクロスリファレンスを実行し、結果が正しいかどうか確認してみましょう。


v10db2_035.jpg



検索処理速度の比較・・・


 さて、実際の検索スピードはどれくらい違うのでしょうか?
 今回のプログラムは、プログラム単位に「あるかないか」を探すだけなので、V10のクロスリファレンス機能のようにプログラム内の該当箇所までを探すものではありません。
 それを承知の上で、単純に結果が出てくるまでの時間を、比較してみたのが次の表です。
(プログラム本数200本程度のアプリケーションで試しました。)

処理内容 MAGIC V10のクロスリファレンス検索
(プログラムのみ)
DB2 9によるsql/xml検索
リポジトリのDB2へのインポート 30秒
プログラムの検索処理時間 20秒 4秒

 さて、如何でしょう?
 百聞は一見にしかずではありませんが、実際に試されてみることをお勧めします。 「これがXMLデータベースというものか!」というようなちょっとした感動があります...。
 高々200行程度のデータベースでも高速に検索してくれますから、大規模なアプリケーションになればなるほど、更に効果が現れるように思います。
 これならリアルタイムでの検索を行わせるようなプログラムを作ったとしても、殆ど実用レベルで動作可能ではないでしょうか?

 今回は小規模のデータだったので、索引は作成していませんが、大規模のデータベースになる場合はXMLドキュメントに索引を作成することも可能です。(このあたりはまたの機会に・・・。)




MAGIC + DB2 で XQuery(1) MAGIC + DB2 で XQuery(1)
サイズ 4320 - File type text/html
MAGIC + DB2 で XQuery(2) MAGIC + DB2 で XQuery(2)
サイズ 7143 - File type text/html
MAGIC + DB2 で XQuery(3) MAGIC + DB2 で XQuery(3)
サイズ 10488 - File type text/html
MAGIC + DB2 で XQuery(4) MAGIC + DB2 で XQuery(4)
サイズ 14638 - File type text/html
V10HACKS_20070329.lzh V10HACKS_20070329.lzh
サイズ 95.6 kB - File type application/x-lzh
カテゴリ
dbMAGIC
DB2

MAGIC + DB2 で XQuery(6)


索引の作成


 ゴールデン・ウイーク真っ只中ですが、皆さん如何お過ごしでしょうか?当方も、あさってあたりボツボツと家族でハイキングなどに出かけようかと思っておるところです・・・。(はっきりとした予定もなく、気の向くままですけれど・・・(^^;)
 さて、あっという間に4月も終わってしまいましたが、その間、IBMさんの技術セミナーにも何度か参加させて頂きました。
 個人的には、DB2の奥の深さに驚くと共に、徐々に愛着が湧きつつあります。なんとか、作成するアプリケーションで生かしたいと思っているところです。

 さて、前回の終わりで紹介させて頂いたXMLデータベースの索引の件ですが、パフォーマンスを考えると、作成方法を知っておく必要があるようです。
 索引を作成するためには、ちょっと面倒なSQL文を作成しないといけないのですが、DB2の基本管理ツール「コントロールセンター」を利用すると、ウィザード的に処理を行うことが可能です。

 下の画面は、コントロールセンターから索引の作成ウィザードを起動したものです。(「DBXML」データベースを選択し、表「XMLDBTEST」をクリック→コンテキストメニューから「作成」→「索引」を選択します。)
 取り敢えず、格納されているデータがサンプルとして表示されます。このXMLデータは、おそらく「メインプログラム」(最初のプログラム)のものだと思われます。たまたま格納したプログラム中に、コールプログラムの定義があったので、そのノードを選んでみました。

v10db2_041.jpg


 上の画面で選んでいる箇所のXPATHは、下記のようになります。

/Application
/ProgramsRepository
/Programs
/Task
/TaskLogic
/LogicUnit
/LogicLines
/LogicLine
/CallTask
/OperationType
/@val

 ウィザードを実行すると「CREATE INDEX」文を作成してくれます。
 しかし、このとき作成されるXPathは、なかなかピッタリしたものにはならないところが玉に瑕(たまにきず)です。

CONNECT TO DB2XML;
CREATE INDEX MUKAIDA.VAL ON DB2ADMIN.XMLDBTEST(DATAXML)
GENERATE KEY USING XMLPATTERN
'//@val' AS SQL VARCHAR(817)
PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS
PAGE SPLIT SYMMETRIC COLLECT STATISTICS ;
CONNECT RESET;
上の構文の中で、「//@val」で表現されてしまっているのが問題のXPathです。本来ならここは「//CallTask/OperationType/@val」としたいところです。(V10のソースの中では、「@val」は至るところに出現します。一般論として「//」のようなXPathの指定は避けられるなら避けたほうが良いらしいのですが、MAGIC V10では、タスク(/Task)は再帰的に出現するので避けることができません。ちなみに、VARCHAR(817)はインデックスのサイズらしいのですが、この再帰的なタスク構造の深さを考慮して、もっと大きい値にすべきかもしれません。)
 そこで、一旦、メモ帳などに貼り付けておいて、下記のように修正しましょう。
 プログラムのリファレンスを検索する場合は、3つのXPathでANDを取る必要があるので、索引は3つ(TEST_IDX1,TEST_IDX2,TEST_IDX3)作成してみました。
CONNECT TO DB2XML;
CREATE INDEX DB2ADMIN.TEST_IDX1 ON DB2ADMIN.XMLDBTEST(DATAXML)
GENERATE KEY USING XMLPATTERN
'//CallTask/OperationType/@val' AS SQL VARCHAR(817)
PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS
PAGE SPLIT SYMMETRIC COLLECT STATISTICS ;
CREATE INDEX DB2ADMIN.TEST_IDX2 ON DB2ADMIN.XMLDBTEST(DATAXML)
GENERATE KEY USING XMLPATTERN
'//CallTask/TaskID/@comp' AS SQL VARCHAR(817)
PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS
PAGE SPLIT SYMMETRIC COLLECT STATISTICS ;
CREATE INDEX DB2ADMIN.TEST_IDX3 ON DB2ADMIN.XMLDBTEST(DATAXML)
GENERATE KEY USING XMLPATTERN
'//CallTask/TaskID/@obj' AS SQL VARCHAR(817)
PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS
PAGE SPLIT SYMMETRIC COLLECT STATISTICS ;
CONNECT RESET;
このように、ウィザードの結果を参考にしながら、修正を加えて使っていけば結構便利かも知れません。


アクセスプランによる索引の検証


 DB2 9には、オプティマイザというものが実装されています。これは、SQL文を処理する際に、使用すべき最適な索引を自動的に選択してくれるものです。
 コマンドエディタを使うと実際に実行されたアクセスプランを確認することが可能です。

 索引を作成する前に実行したアクセスプランが次のものです。

v10db2_042.jpg

 索引を作成した後で実行したアクセスプランは次のように変わります。

v10db2_043.jpg

 この例では、作成した索引(TEST_IDX1~3)が使用され、パフォーマンスも良くなっていることが分かります。
 ただ、問題はどこにどのように索引を付けるか・・・です。
 今回は、実行するSQL文に合わせて索引を作成しましたから、「正しく索引を付ければパフォーマンスが上がる」ことを検証したに過ぎません。
 このあたりの問題は、DB2 9のオートノミックな機能に任せるべきところ、アプリケーションとしてチューニングを必要とするところ、それぞれの見極めが必要でしょう。

p.s
 今回は、なんかMAGICの話が出てきませんでしたが、ごめんなさい。
 いろいろと話題を準備しておりますので、楽しみにしていて下さい。
 最新版のMAGIC V10(10.1 SP2)で出力したサンプルプログラムをアップしておきます。

 <改良点>
  1.   「プログラム一覧」のコンテキストメニューに「XMLインポート」を追加し、表示中のプログラムソースを一括してDB2にインポートできるようにしました。
  2. プログラム14に、「データベースと表の作成」プログラムを追加しました。これにより、使用するDB2のデータベースと表を一括して作成します。結果はコマンドプロンプト内に表示します。








MAGIC + DB2 で XQuery(1) MAGIC + DB2 で XQuery(1)
サイズ 4320 - File type text/html
MAGIC + DB2 で XQuery(2) MAGIC + DB2 で XQuery(2)
サイズ 7143 - File type text/html
MAGIC + DB2 で XQuery(3) MAGIC + DB2 で XQuery(3)
サイズ 10488 - File type text/html
MAGIC + DB2 で XQuery(4) MAGIC + DB2 で XQuery(4)
サイズ 14638 - File type text/html
MAGIC + DB2 で XQuery(5) MAGIC + DB2 で XQuery(5)
サイズ 7537 - File type text/html
V10HACKS_20070502.lzh V10HACKS_20070502.lzh
サイズ 111.6 kB - File type application/x-lzh
カテゴリ
dbMAGIC
DB2