IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  Information Management | Open source  >

DB2 と Ruby on Rails: 第2回 Ruby on Rails を使用した DB2 と pureXML

Ruby on Rails による pureXML のネイティブ XML サポート - Web アプリケーション開発のための強力な組み合わせです

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

サンプルコード

原文はこちら

原文はこちら


レベル: 中級

John Chun, DB2 Advanced Support Specialist, IBM 
Christine Law, DB2 Advanced Support Specialist, IBM 
Salvador Ledezma, Staff Software Engineer, IBM
Alex Pitigoi, Advisory Software Engineer, IBM

2007年 6月 07日

XML は、今日の Web で最もよく使用されるデータ交換フォーマットの 1 つとして数えられています。DB2® の pureXML™ サポートを Ruby on Rails に用意された XML API (REXML) の解析および生成と組み合わせると、Web アプリケーション開発のための強力な組み合わせになります。DB2 データ・サーバーにおけるネイティブ XML サポートは、そのハイブリッド・データベース・エンジンのコンパイラーとパーサーを利用して、リレーショナル・データと併せて半構造化された階層構造の XML 文書を保管するという柔軟性をもたらし、SQL と XQuery の両方に対応します。連載「DB2 と Ruby on Rails」の第 2 回では、第 1 回の記事で使用したサンプル・アプリケーション Team Room を実例に用いて pureXML を活用する方法を説明します。

はじめに

連載「DB2 と Ruby on Rails」の第 1 回では、Ruby on Rails と DB2 を使って Team Room をビルドしました。これは、登録されたメンバーが各種のテキスト文書、画像ファイル、そして XML 文書を共有できるようにするアプリケーションです。このアプリケーションを使って、増え続ける共有文書を管理するために文書をカテゴリー別に分類し、それからサブスクリプション機能を追加して、新しい文書が文書カテゴリーに加えられたときにそのカテゴリーをサブスクライブしているユーザーに E メールで通知する方法を説明しました。記事の最後では、メンバーがさまざまな種類のファイルを Team Room にアップロードしてバックエンドの DB2 データ・サーバーに保管できるようになりました。今回は、Team Room を拡張してさらに高度なユーザー機能を提供し、リソースへのアクセスを改善します。




上に戻る


開発を進めるための Team Room アプリケーションの更新、パート 1

ステップ 1. ユーザー管理機能を追加する

まず、ユーザー・モデルとその基礎となる表のパーシスタンスに必要な追加を行って、適切な認証を有効にするところから始めましょう。追加するのは固有のユーザー ID ストリングと、SHA アルゴリズムを使用して擬似ランダム・シード (salt) でハッシュ化したパスワードです。ここではコントローラーと表示に多少の変更を追加して新規ユーザーの登録とセキュアなログインを可能にしていますが、このユーザー・モデルに他のユーザー属性 (アクティブであるか、ランクなど) を追加すればさらに改善することができます。サンプルの Rails プロジェクトは D:\rails\teamroom に置かれているので、以下で参照しているすべてのパスは、D:\rails\teamroom ディレクトリー内での相対パスです。

a) ruby script/generate migration add_user_credentials_columns を実行して、USERS 表に必要な列を追加するためのマイグレーション・プロセスを開始します。

b) db/migrate/008_add_user_credentials_columns.rb ファイルを編集して必要な列を追加します (リスト 1 を参照)。


リスト 1. 008_add_user_credentials_columns.rb の編集
                                
class AddUserCredentialsColumns < ActiveRecord::Migration
  def self.up
    add_column    :users, :userid,      :string, :limit => 8
    add_column    :users, :hash_passwd, :string
    add_column    :users, :salt,        :string
  end

  def self.down
    remove_column :users, :userid
    remove_column :users, :hash_passwd
    remove_column :users, :salt
  end
end

c) rake db:migrate を実行して上記の新しい列を USERS 表に追加します。

ステップ 2. サブジェクトを複数のユーザー・サブスクリプションで利用できるようにする

前回の記事で説明した Team Room アプリケーションでは、それぞれのサブジェクトは 1 つのサブスクリプションにしか属せませんでした。各サブスクリプションはユーザーがサブスクライブしたサブジェクトの集合であることを思い出してください。このため、ユーザーが特定のサブジェクトを選択すると、選択されたサブジェクトは Team Room の残りのユーザーには利用できなくなってしまい、Team Room を非現実的なアプリケーションにしているのです。

Team Room の人気を考えると、多くのメンバーが複数のサブジェクトをサブスクライブしたいと思うはずです。ここはメンバーの要求に応えて、1 つのサブジェクトに複数のサブスクリプションを許可するしかありません。そこで、更新後の Team Room では、単一のサブジェクトを複数のサブスクリプションで利用できるようにしています。そのために実装する変更は以下のとおりです。

  • 以前は、SUBSCRIPTIONS と SUBJECTS の関係は 1 対多でした。ただし、各サブジェクトが属せるのは 1 つのサブスクリプションだけです。この制限を解除するには、SUBSCRIPTIONS と SUBJECTS との間で多対多の関係を許可する必要があります。
  • データベースを確実に正規化するため (注 1 を参照)、SUBJECTS_SUBSCRIPTIONS という新しい表を作成して SUBJECTS 表と SUBSCRIPTIONS 表を結合します。この名前を見るとわかるように、中間結合表の名前には Rails の規則を使用します。アクティブ・レコード (Active Record) は、この結合した表の名前が 2 つのターゲット表の名前をアルファベット順に連結したものであるいう前提で、2 つのターゲット表をリンクする外部キーのペアを格納します。
  • 既存の関連を変更し、変更を反映するために新しい関連を SUBJECTS_SUBSCRIPTIONS 表、サブジェクト、およびサブスクリプション・モデルに追加します。
注 1: DB2 Database for Linux, UNIX, and Windows インフォメーション・センターの「正規化」セクションを参照してください。

SUBJECTS_SUBSCRIPTIONS 表に含まれる列は以下のとおりです。


表 1. SUBJECTS_SUBSCRIPTIONS 表の列とその説明
列名データ型説明
SUBSCRIPTION_ID整数SUBSCRIPTIONS 表の外部 ID
SUBJECT_ID整数SUBJECTS 表の外部 ID

マイグレーションという方法で変更を実装するには、以下のステップに従います。

a) ruby script/generate migration create_subjects_subscriptions_table を実行します。

b) db/migrate/009_create_subjects_subscriptions_table.rb ファイルを以下のように編集します。



リスト 2. 009_create_subjects_subscriptions_table.rb の編集
                                
class CreateSubjectsSubscriptions < ActiveRecord::Migration
  def self.up
    create_table :subjects_subscriptions,  :id   => false do |t|
      t.column :subscription_id, :integer, :null => false
      t.column :subject_id,      :integer, :null => false
    end  
    remove_column :subjects, :subscription_id
    add_index     :subjects_subscriptions, :subject_id
  end

  def self.down
    drop_table    :subjects_subscriptions
    add_column    :subjects, :subscription_id, :integer
  end
end

c) rake db:migrate を実行して SUBJECTS_SUBSCRIPTIONS 表を作成します。

d) /app/models/subject.rb ファイルで、既存の関連 belongs_to :subscription を新しい関連 has_and_belongs_to_many :subscriptions に置き換えます。

e) /app/models/subscription.rb ファイルで、既存の関連 has_many: subject has_and_belongs_to_many :subjects に置き換えます。

注 2: マイグレーションを元に戻す場合は、それぞれのモデルのデータベース・オブジェクトとの関連が変更されて適切に元に戻っていることを確認してください。

ステップ 3. XML データ: 顧客情報

マーケティング・チームでは顧客の購買傾向を分析するため、匿名の顧客情報を XML 形式で収集しました。以下は、小売業者が市場調査のために収集すると考えられるデータの例です。


リスト 3. XML 文書の例
                                
<marketinfo xmlns="http://www.ibm.com/developerworks">
  <sales>
    <customer>
      <address>
        <city>Nashville</city>
        <state>TN</state>
        <zip>46808</zip>
      </address>
      <categories>
        <category type='Toys'>
          <item>
            <SKU>2434901</SKU>
          </item>
          <item>
            <SKU>9043272</SKU>
          </item>
        </category>
        <category type='Video Games'>
          <item>
            <SKU>1915216</SKU>
          </item>          
        </category>
      </categories>
      <last_purchase>2007-05-12</last_purchase>
    </customer>
  </sales>
</marketinfo>

それぞれの顧客購入情報には、米国またはカナダ国内の住所、製品カテゴリーの詳細 (商品の SKU (Stock Keeping Unit: 在庫保管単位) 番号など)、そして前回の購入日が含まれます。製品カテゴリーには以下のものがあります。

  • 衣料
  • 自動車
  • 赤ちゃん用品
  • コンピューター
  • 化粧品
  • 電化製品
  • 園芸用品
  • 家庭用品
  • ジュエリー
  • 映画
  • 音楽
  • ペット
  • 医薬品
  • スポーツ
  • 玩具
  • テレビ・ゲーム

Team Room アプリケーションを使って上記の XML データにクエリーを実行する方法については、次のセクションで説明します。

この XML 形式の顧客データには、テキスト文書形式の市場調査レポートを関連付けることができます。市場調査レポートには市場分析、あるいはデータ収集方法の詳細を含められます。

第 1 回で、収集したマーケティング・データを保管する XML 型の列を作成したことを思い出してください。DB2 は XML データを従来の SQL データ型と同じように効率的に管理するため、内部では XML データ・モデルを論理データ・モデルとして使用するとともに、物理ストレージの基本単位としても使用します。さらに、XML データ型が指定されたときにはこのデータ・モデルがデータベースのユーザーに公開されます。このような仕組みは、特に XML 中心の開発者にとって XML データの管理を強力かつ柔軟に行えるようにしていますが、現時点では、従来のデータベース管理アクティビティーのタイプによっては XML 列で実行できることに制限があります。例えば、XML の階層ストレージ構造のために、DB2 では XML 列を持つ表を物理的に再編成することができません。つまり事実上、XML 列が含まれる表では ALTER 操作によって列を削除できないということです。この制約は今後のリリースで取り除かれる可能性がありますが、ALTER 操作は Ruby on Rails のマイグレーションに基本的な操作なので覚えておいてください。

XML ならではの利点を生かしつつも Ruby on Rails のマイグレーションが持つ柔軟性を損なわないようにする方法は、XML データを保管する別の表を作成することです。サンプル・アプリケーションでは、この表を XML_CONTENTS と呼ぶことにします。この表に XML 文書を保管し、他のすべての関連情報は DOCUMENTS 表に今までどおり保管します。このようにすれば、DOCUMENTS 表の列を追加または削除するときに、XML データによって影響されたり、XML_CONTENTS 表の XML データに影響したりすることがありません。

XML データ型を使用する上での現在の制約事項についての詳細は、IBM DB2 Database for Linux, UNIX, and Windows インフォメーション・センターの「ネイティブ XML データ・ストアの制約事項」を参照してください。

XML データを保管する別の表を作成するには、以下のマイグレーションを実行します。

a) ruby script/generate migration create_xml_contents を実行します。これによって、db/migrate/010_create_xml_contents.rb ファイルが作成されます。

b) db/migrate/010_create_xml_contents.rb ファイルを以下のように編集します。


リスト 4. 010_create_xml_contents.rb の編集
                                
class CreateXmlContents < ActiveRecord::Migration
  def self.up
    drop_table :documents
    create_table :documents do |t|
      t.column :name,         :string,   :null => false
      t.column :size,         :integer,  :null => false
      t.column :data,         :binary,   :limit => 2.megabytes
      t.column :content_type, :string,   :null => false
      t.column :created_at,   :timestamp
      t.column :updated_at,   :timestamp
      t.column :platform,     :string,   :limit =>10
      t.column :subject_id,   :integer
      t.column :user_id,      :integer
    end
    create_table :xml_contents do |t|
      t.column :name,        :string
      t.column :data,        :xml,       :null => false
      t.column :document_id, :integer
    end
  end

  def self.down
    drop_table :documents
    drop_table :xml_contents
    create_table :documents do |t|
      t.column :name,           :string,   :null => false
      t.column :size,           :integer,  :null => false
      t.column :data,           :binary,   :limit => 2.megabytes
      t.column :content_type,   :string,   :null => false
      t.column :created_at,     :timestamp
      t.column :updated_at,     :timestamp
      t.column :platform,       :string,   :limit =>10
      t.column :subject_id,     :integer
      t.column :user_id,        :integer
      t.column :xmldata,        :xml,      :null => false
    end
  end
end

c) rake db:migrate を実行して既存の DOCUMENTS 表を削除し、XML_CONTENTS という名前の XML データ専用の新しい表と、XML 列がない新しい DOCUMENTS 表を作成します。

d) 新しい DOCUMENTS 表と XML_CONTENTS 表との関係を再設定します。

まず、ステップ d で生成された /app/models/xml_content.rb ファイルに関連 belongs_to :document を追加します。

次に、/app/models/document.rb ファイルに関連 has_one :xml_content を追加します。

e) アップロード機能は、以前に前の文書モデル (document.rb) に実装した内容と同様です。今ではこの文書モデルが親モデルとなり、子モデル (xml_content) を作成するための処理を追加します。

NAME 列には元のファイル名が入力されます。


リスト 5. DOCUMENTS レコードへのファイル属性の割り当て
                                
self.name = File.basename(doc_field.original_filename).gsub(/[^\w._-]/, '')
self.content_type  = doc_field.content_type.chomp
self.size = doc_field.size
self.created_at = Time.now

XML_CONTENTS.DATA 列には指定されたファイルが入力されます。



リスト 6. XML_CONTENTS.DATA への XML ファイル・コンテンツの割り当て
                                
unless self.content_type.include?('text/xml')
  self.data = doc_field.read
else
  content = XmlContent.new
  content.name = self.name
  content.data = doc_field.read
  self.xml_content = content
end

最終的な /app/models/document.rb はリスト 7 のようになっているはずです。



リスト 7. document.rb
                                
class Document < ActiveRecord::Base
  belongs_to  :user
  belongs_to  :subject
  has_one     :xml_content

  #           values  displayed  |  stored
  PLATFORM_TYPES = [ ['Neutral',    'Any'],
                     ['Windows',    'WinXP'],
                     ['Mac OS X',   'MacOS'],
                     ['Linux',      'Linux']]


  def uploaded_doc=(doc_field)
    self.name = File.basename(doc_field.original_filename).gsub(/[^\w._-]/, '')
    self.content_type  = doc_field.content_type.chomp
    self.size = doc_field.size
    self.created_at = Time.now
    unless self.content_type.include?('text/xml')
      self.data = doc_field.read
    else
      content = XmlContent.new
      content.name = self.name
      content.data = doc_field.read
      self.xml_content = content
    end
  end
end

XML_CONTENTS 表と DOCUMENTS 表のモデルを定義したら、今度はアップロード機能と文書のリスト表示を変更します。サンプル・アプリケーションではアップロード機能と文書のリスト表示を更新して、表示対象のモデル属性 (列) を明示的に選択するようにしてあります。

/app/views/documents/list.rhtml ではこの明示的な列の選択を以下のように実装します。



リスト 8. /app/views/documents/list.rhtml
                                
<table cellpadding="0" cellspacing="0">
  <tr>
   <th>ID</th>
   <th>Document name</th>
   <th>Subject</th>
   <th>Shared by</th>
   <th>Size</th>
   <th>Update at</th>
   <th>Platform</th>
   <th></th>
   <th></th>
   <th></th>
  </tr>
  <% @documents.each_with_index do |document,i| %>
    <% row_class = i%2 ==0 ? "even" : "odd" %>
    <tr class="<%=row_class%>">
    <td><%= document.id %></td>
    <td><%= document.name %></td>
  <% if document.subject %>
    <td><%= link_to "#{document.subject.name}", 
                     :controller => 'subjects', :action => 'list'  %></td>
  <% else %>
    <td></td>
  <% end %>
  <% if document.user %>
    <td><%= link_to "#{document.user.userid}", 
                     :controller => 'users', :action => 'list'  %></td>
  <% else %>
    <td></td>
  <% end %>
    <td><%= number_to_human_size( document.size ) %></td>
    <td><%= document.updated_at.strftime("%d/%m/%Y %I:%M%p") %></td>
    <td><%= document.platform %></td>
    <td><%= link_to 'Show', :action => 'show', :id => document %></td>
    <td><%= link_to 'Edit', :action => 'edit', :id => document %></td>
    <td><%= link_to 'Remove', { :action => 'destroy', :id => document }, 
                     :confirm => 'Are you sure?', :method => :post %></td>
    </tr>
  <% end %>
</table>

次に、XML データの場合の文書表示機能を処理するため、コントローラーを以下のように更新しました。これらのエントリーは /app/controllers/documents_controller.rb に追加します。



リスト 9. documents_controller.rb
                                
def show
  @document = Document.find(params[:id])
  doc_type = @document.content_type
  unless doc_type.include?('text/xml')
    doc_content = @document.data
  else
    doc_content = @document.xml_content.data
  end
  send_data(doc_content,
            :filename => @document.name,
            :type => doc_type,
            :disposition => "inline")
end

さらに XML 文書のアップロードをサポートするために以下の更新も行いました。これを見ると、サブジェクトとユーザーの関係の処理に文書が実装されていることがわかります。



リスト 10. documents_controller.rb
                                
def upload
  if params[:document][:uploaded_doc].to_s.empty?
    flash[:notice] = "Please provide a file for upload"
    redirect_to(:action => "new" )
  else
    @document = Document.new(params[:document])
    @subject = params[:subject_name] && params[:subject_name].empty? ? 
               Subject.new :
               Subject.find_by_name(params[:subject_name])

    Document.transaction do
      User.find(session[:user_id]).documents << @document
      @subject.documents << @document
      @subject.size = @subject.documents.size
      if @subject.new_record?
        @subject.name = params[:subject][:name]
        @subject.tag = params[:subject][:tag]
        @subject.description = params[:subject][:description]
        @subject.save
      end

      if @document.save
        flash[:notice] = "Document #{@document.name} successfully created."
        if @document.subject.subscriptions
          SubscriptionMailer.deliver_notify(@document)
        end
        redirect_to :action => 'list'
      else
        render :action => 'new'
      end
    end
  end

以下の図 1 に、上記のマイグレーション・ステップを実行した後の Team Room に含まれるモデルの相互関係を示します。



図 1. 変更後のモデル間の新たな関係




上に戻る


Team Room への XML マーケティング・データのアップロード

注 3: IMPORT コマンドでインポートできるのは、整形式 XML 文書のみです。

注 4: XML スキーマを削除するには、以下のコマンドを使用します。

drop xsrobject teamroom.marketinfo

マイグレーションによってスキーマに必要な変更をすべて実装したので、今度は XML データを XML_CONTENTS 表にアップロードする作業に取り掛かります。複数の XML 文書を表に挿入するのに最も簡単な方法は、DB2 9 データ・サーバーの IMPORT ユーティティーを使うことです。IMPORT ユーティリティーを使用すると、XML スキーマの妥当性検証の有無に関わらず整形式 XML 文書をインポートすることができます。このサンプルでは、XML_CONTENTS 表と DOCUMENTS 表、そして SUBJECTS 表内の関連するエントリーを正しく確実に更新しなければなりません。そのため、生成された基盤を使用して一度に 1 ファイルずつデータのアップロードを行い、すべての外部キーの関連が維持されるようにします。

図 2 に記載した文書の表示 /app/views/documents/new.rhtml には、XML コンテンツに関連付ける文書の作成と、この新しい文書に関連付ける新規サブジェクトの作成が示されています。



図 2. Team Room リポジトリーへの XML 文書のアップロード

XQuery 検索と XPath 検索の演習で使用するカナダと米国の一部の地域をシミュレートしたマーケティング・データが含まれる残りの XML 文書をアップロードするには、今がちょうどいい機会です。XML ファイルが配置されているのは、/test/fixtures の下です。ここには検証のために使用する marketinfo.xsd XML スキーマもあります。更新された Team Room アプリケーションを入手するには、この記事の終わりにある「ダウンロード」セクションを参照してください。





上に戻る


XML データ型での基本 CRUD 操作

ここで、XML データの管理方法を学ぶ最初の一歩として基本的な XML CRUD (Create, Retrieve, Update, and Delete) 操作を実行してみましょう。

CRUD 操作を説明するため、ここではマーケティング・チームが顧客の居住都市の調査に関心を持っているとします。顧客の認知度を高めて店舗に再び足を運ばせるために、顧客が住む都市でのマーケティング・キャンペーンを企画しているという想定です。それに備えて私たちができるのは、XML_CONTENTS 表に保管されたマーケティング情報に関する XML 文書からデータを抽出することです。さらに、拡大し続けている対象都市のリポジトリーを (継続的に) 追跡するために作成された調査情報を保管することにしました。この都市のデータベースを XML として作成すれば、別の表を作成してデータを追跡することを心配しなくても済むことに注目してください。情報を XML 文書として作成して、同じ列に XML として挿入しなおせばいいだけの話だからです。今後のある時点で、DBA がアプリケーション・データと分けるために新しい表を作成することを考えるかもしれませんが、それは完全に論理的なセマンティック上の要件なので、このデータベースには必要のないことです。

DB2 では、XML データに対してクエリーを実行するのに SQL、XQuery、あるいはこの 2 つの組み合わせを使用できます。この例では XQuery を使います。XQuery を使用すると、返されたクエリーの結果を XML 文書を構成する際の値として使用するのが簡単だからです。リスト 11 に、実行する XQuery を記載します。


リスト 11. 都市調査の XQuery
                                
XQUERY
<cities>
   declare default element namespace "http://www.ibm.com/developerworks";
   { for $c in fn:distinct-values(
         db2-fn:xmlcolumn(
        'XML_CONTENTS.DATA')/marketinfo/sales/customer/address/city)
         order by $c
      return <city>{$c}</city>
   }
</cities>

まずはステートメント内にある関数 db2-fn:xmlcolumn() から、この特定の XQuery がどのように動作するかを説明していきます。db2-fn:xmlcolumn() は、現在接続している DB2 データベースの XML 列からシーケンスを取得する関数です。上記では、XML_CONTENTS 表の DATA 列からデータを取得しています。ただし、必要なのは DATA 列に含まれるすべてのデータではなく、XPath 式 /marketinfo/sales/customer/address/city で識別されるサブセットだけです。

つまり、表に含まれるすべての行のすべての XML 文書を調べ、XPath に出てくる city 要素すべてを選択するわけですが、これによって問題が発生する可能性があります。複数の顧客が同じ都市に住んでいることが考えられるためです。その点を考慮して使用しているのが、XQuery 関数fn:distinct-values() です。名前が示すように、この関数は他と重複しない city 要素のシーケンスだけを返すため、都市名が繰り返されることはありません。このシーケンスは変数 $c に割り当てられます。

最後に$c の都市を並べてから、結果を返します。XQuery を極めて有能にしている特徴の 1 つは、返されるデータのフォーマットを高度にカスタマイズできるという点です。今のところ都市名のシーケンスはあるので、それぞれの city 要素を <cities> 要素でラップします。これは要素のシーケンスですが、ルート要素がないため妥当な XML 文書にはなっていません。妥当な XML 文書が返されるようにするには、結果全体を <cities> 要素のなかに配置します。すると、 リスト 12 のような昇順のデータが返されます。


リスト 12. 返される典型的な XML データ
                                
<cities>
  <city>Atlanta</city>
  <city>Augusta</city>
  <city>Austin</city>
  <city>Baton Rouge</city>
  <city> ... </city>
</cities>

DB2 9 での XQuery の詳細は、DB2 XML Guide を参照してください (記事の終わりにある「参考文献」にリンクを記載しています)。

都市のリストが XML 文書になったので、今度はこの文書をデータベースに戻します。開発者は、あらゆる型のデータをデータベースに挿入する場合と同じように XML 文書を挿入するはずです。


リスト 13. XML 文書の挿入
                                
class DocumentsController < ApplicationController
  [...]
  def upload
  [...]
      @document = Document.new(params[:document])
      @subject = params[:subject_name] && params[:subject_name].empty? ? 
                 Subject.new :
                 Subject.find_by_name(params[:subject_name])

      Document.transaction do
        User.find(session[:user_id]).documents << @document
        @subject.documents << @document
        @subject.size = @subject.documents.size
        if @subject.new_record?
          @subject.name        = params[:subject][:name]
          @subject.tag         = params[:subject][:tag]
          @subject.description = params[:subject][:description]
          @subject.save
        end
  
        if @document.save
          flash[:notice] = "Document #{@document.name} successfully created."
  [...]
end

顧客の数は常に静的であるわけではないので、リストを最新の状態に維持するには顧客の都市リストを例えば毎週、あるいは毎月定期的に更新しなければなりません。それには、同じ XQuery ステートメントを実行し、現在データベース内にある文書をその id に基づいて最新バージョンの XML ファイルに置き換えます。注目すべき点は、既存の文書を隠し :id パラメーターで取得する方法です。このパラメーターが、DocumentsController で使われる編集表示フォーム (/app/views/documents/_form.rhtml) に渡されます。


リスト 14. XML 文書の更新
                                
class DocumentsController < ApplicationController
  [...]
  def update
    @document = Document.find(params[:document][:id])
    if @document.update_attributes(params[:document])
      flash[:notice] = 'Document was successfully updated.'
      redirect_to :action => 'show', :id => @document
    else
      render :action => 'edit'
    end
  end
  [...]
end

内部では DB2 が既存の XML データ・ページの割り当てを解除し、新しい値が挿入し直されます。このように効率的に、XML 文書全体が更新された新しい文書に置き換えられるというわけです。

このデータがいずれ無用になったり、あるいは他のメカニズムで処理されるようになることも考えられます。例えば、DBA が別の表の別の XML 列を使用するなどしてコンサーン (対象) の分離をしようと主張した場合です。 文書を削除するには、適切な WHERE 述部を使って DELETE 文を実行します。 Ruby では、例えば以下のように実行できます。


リスト 15. XML 文書の削除
                                
class DocumentsController < ApplicationController
  [...]
  def destroy
    Document.find(params[:id]).destroy
    redirect_to :action => 'list'
  end
end




上に戻る


XML データに対するクエリーの実行

基本 CRUD 操作だけでなく XQuery 言語の機能を使用すれば、どのようなクエリーを作成して、どのような形でデータが返されるようにするかを極めて詳細に指定することができます。例えば、顧客が住んでいる都市のリストも役立ちますが、マーケティング・チームではそれよりも、どの製品カテゴリーがアクティブであるかにもっと興味があるかもしれません。どの製品に人気があるかがわかれば、マーケティング・キャンペーンですべての製品を網羅するだけの予算を見込めないマーケティング・イニシアチブの焦点をさらに絞り込むことができます。アクティブな製品であることを示す 1 つの測定指標は、特定の製品カテゴリーで最近販売実績があったかどうかです。もっと限定すれば、これらの製品カテゴリーが特定の期間中にアクティブであったかどうかです。

データ・マイニング作業は、2007年4月15日から 4月30日の間に販売実績があった製品カテゴリーは何かという質問を提示することから始めます。

リスト 16 は、マーケティング・チームが提示した質問に答えるためのクエリーです。


リスト 16. 4月15日から 4月30日までの製品カテゴリーの購入情報を取得するための XQuery
                                
XQUERY
declare default element namespace "http://www.ibm.com/developerworks";
<categories>
  { let $categories := fn:distinct-values( 
      for $c in db2-fn:xmlcolumn( "XML_CONTENTS.DATA")/marketinfo/sales/customer
          where xs:date($c/last_purchase) >  xs:date("2007-04-15")
            and xs:date($c/last_purchase) <= xs:date("2007-04-30")
         return $c/categories/category/@type)
      for $c in $categories 
         return <category>{$c}</category>
  }
</categories>

前の例と同じく妥当な XML 文書を返す必要があるので、XQuery の結果を <categories> ルート XML 要素でラップします。ラップされた XQuery は 2 つの部分で構成されます。まず、$categories 変数に式をバインディングする「let」文、そしてこの変数が for 文のコンテキストで使われる部分です。それぞれについて個別に検討してみましょう。

「let」文自体は XQuery 式 の FLWOR (for、let、where、order by、return) で構成されます。ご存知かもしれませんが、FLWOR 表現はよく SQL の SELECT-FROM-WHERE ブロックと比較されます。上記ではまず、for $c in db2-fn:xmlcolumn("XML_CONTENTS.DATA") /marketinfo/sales/customer ですべての顧客を繰り返し処理しています。購入日の条件は、2007年4月15日から 2007年4月30日までの間であり、マーケティング・チームが知りたいのはこの基準を購入情報が満たすかどうかなので、where xs:date($c/last_purchase) > xs:date("2007-04-15") and xs:date($c/last_purchase) <= xs:date("2007-04-30") としています。

基準を満たす購入情報のなかからは、XML 属性として格納されたカテゴリーのタイプ $c/categories/category/@type を返します。前回の例と同じく、同じカテゴリーが重複しないように fn:distinct-values() 関数を使用します。このカテゴリー・リストが、$categories 変数にバインドされます。

この時点で $categories には重複のないカテゴリーのシーケンスが保管されることになりますが、この例で返すのは XML なので、シーケンスに含まれるそれぞれの値を <category> XML 要素でラップします。最終的な出力は、リスト 17 のようになります。このリストは確実に、4月15日から 4月30日までの購入情報が含まれるようにフィルタリングされています。


リスト 17. 、4月15日から 4月30日までに販売実績があった製品カテゴリーのデータ例
                                
<categories>
  <category>Home</category>
  <category>Electronics</category>
  <category>Apparel</category>
  <category>Gifts & Flowers</category>
  <category>Baby</category>
</categories>

この XQuery をパラメーター化すれば、マーケティング・チームが望むどんな日付の範囲のクエリーでも実行できるようになります。さらに、このクエリーをカプセル化するために、この機能をストアード・プロシージャーにして、Rails 開発者用に XQuery の詳細を抽象化することができます。

図 3 に記載する文書のリスト表示 /app/views/documents/list.rhtml のレイアウトには、XQuery 検索と XPath 検索を実行できる事前ビルド済みのレポート・フォームも含まれています。



図 3. Team Room の文書リポジトリーと事前ビルドされたマーケティング・レポート




上に戻る


巨大な XML データに対するクエリーの実行

クエリーの方法に慣れてきたところで、マーケティング・チームのデータに対する要求が幾分厳しくなってきました。今度は、特定の郵便番号が含まれる地域での特定のカテゴリー・タイプの製品販売数を知りたがっています。この郵便番号は、大量の販売数があった地区であることも、苦情がたくさん寄せられた地区であることもあります。このような情報があれば、マーケティング・マネージャーと製品マネージャーは、どの販売地域でどの製品に人気があるかを該当する郵便番号と結び付けて判断することができます。そして地域での製品の人気に応じて、販売を打ち切るべき製品や、マーケティング活動で重点を絞るべき郵便番号を見極められるはずです。

この要求に応えるために使うのは、SQL/XML 関数 XMLQUERY() です。SQL/XML を使ってクエリーを実行すると、両方の機能を合わせて使うことができます。例えば、SQL/XML では以下の操作を実行することができます。

  1. リレーショナル・データと XML データの両方で述部を使用する
  2. XML データのフラグメントにアクセスして抽出する
  3. SQL レベルで XML データの集約とグループ化を使用する
  4. リレーショナル・データと XML データを結合する
  5. パラメーターを XQuery 式に渡す

ここで説明する XQuery では上記のうち、(1)、(2)、(5) を使用します。簡潔にするためサンプルをパラメーター化することはせずに、郵便番号「79081」でのカテゴリー・タイプ「Jewelry (ジュエリー)」に興味があるという前提にします。マーケティング・チームにとって幸いなことに、付属のアプリケーション・コード (この記事の終わりにある「ダウンロード」セクションを参照) に記載されているクエリーのバージョンでは、パラメーターをあらゆるカテゴリー・タイプまたは郵便番号にすることができます。


リスト 18. 特定の郵便番号で販売された全カテゴリー・タイプを取得する SQL/XML クエリー
                                
select name, xmlquery( 
               'declare default element namespace "http://www.ibm.com/developerworks";
                 let $total := sum (
                                    for $i in $t//category 
                                       let $sum := count($i/item)
                                       where $i/@type = "Jewelry"
                                    return $sum
                                    )
                return <total>{$total}</total>'
                   passing data as "t"
                      ) as data 
      from teamroom.documents
      where xmlexists( 
                'declare default element namespace "http://www.ibm.com/developerworks";
                 $t/marketinfo/sales/customer/address[zip = "79081"]'
                    passing data as "t"
                      )

上記では、SELECT 文を使用して、name 列で識別された領域ごとに 1 行返しています。さらにそれぞれの行について、<total> ルート要素だけが含まれる有効な xml 文書を返します。ここでは XQuery を SQL 言語のなかで呼び出しているため、SQL/XML 関数 XMLQUERY() を使って XQuery エンジンが操作対象のコンテキストを認識するようにしなければなりません。これまでの例では db2-fn:xmlcolumn() 関数を使用して対処していましたが、今回はデータをtとして渡す節を使用します。つまり、データを操作対象の XML 列として識別し、変数 tを割り当てるということです。$t 変数が XQuery 内のどこにあっても、DB2 はそれを認識し、SELECT 文の現在の行に含まれる data 列の XML 文書を置換します。

SQL レベルで行われているもう 1 つの異なる点は、XMLQUERY() を列内のすべての XML 文書に対して実行しているわけではないという点です。クエリーを実行するのは郵便番号が「79081」の顧客が含まれる行に制限し、該当する行を見つけたら、それらの行でだけ XQuery を実行します。具体的には、その行に含まれるすべての顧客に対しては、郵便番号が「79081」であるかないかに関わらずクエリーを実行します。

このフィィルタリングを行うのが、SQL/XML XMLEXISTS() 関数述部を使用した SQL WHERE 節です。XMLEXISTS 述部は、XQuery クエリーが 1 つ以上の要素のシーケンスを返すかどうかを判断します。上記の例で XMLEXISTS() に渡している XQuery 式は、単純な XPath 式で $t は XML 列 data: $t/marketinfo/sales/customer/address[zip = "79081"] です。

この XPath 式は、zip が「79081」の address 要素のシーケンスを返すという意味に解釈できます。指定された XPath が空のシーケンスを返すと XMLEXISTS は false を返し、そうでなければ true を返します。SQL によって XML 文書のサブセットを取得できたので、今度は XQuery で $total 変数への let バインディングを使う番です。$total には FLWOR 式の結果が割り当てられます。XML 文書に含まれる、タイプが「ジュエリー」(where $i/@type = "Jewelry") のすべての <category>要素 (for $i in $t//category) について、販売数をカウントしてその値を $sum に割り当て (let $sum := count($i/item))、合計を返します (return $sum)。

上記のコードによって返されるのは、顧客ごとの合計のシーケンスです。この結果が $sum 関数に渡され、すべての顧客でその特定カテゴリーについての合計が取得されます。ここで $total を返すわけですが、これは XML でなければならないので <total> 要素でラップします (return <total>{$total}</total>')。最終的には、return <total>198</total>' のような結果になります。

DB2 9 で XQuery を使用する方法の詳細と例については、DB2 XML Guide (「リソース」セクションにリンクを記載) を参照してください。




上に戻る


XML データのシュレッディング

例えば 1 つのシナリオとして、新しくビルドしたアプリケーションがあり、これをネイティブ XML に対応していないレガシー・アプリケーションとリポジトリーに統合しなければならないとします。この場合、XML 文書に保管された情報をリレーショナル表オブジェクトに配置しなければなりません。

あるいは市場分析の結果をレガシー・アプリケーションで分析するためにリレーショナル・ストアに提供するというシナリオを考えてみてください。それには XML データのシュレッディングを行いリレーショナル表に挿入できるようにする必要があります。

すでに説明したように、pureXML には XML データを直接操作するための多数の機能があります。必要であれば、pureXML では分解としても知られるシュレッディングを実行することもできます。DB2 9 データ・サーバーには、XML のシュレッディングを簡単に行える以下のツールが組み込まれています。

1. XDBDECOMPXML ストアード・プロシージャー

DB2 9 のアノテーション付き XML スキーマ分解機能を使用すると、XML 文書をリレーショナル表に分解することができます。名前が示すとおり、この機能は XML スキーマのアノテーション (注釈) をマッピング言語として使用して XML 文書内の情報をリレーショナル表にマッピングします。それには XML スキーマが必要になるため、XML スキーマ文書を DB2 XSR に保管して分解用に指定してください。XML 文書をマッピングされたリレーショナル列に分解、あるいは「シュレッディング」するには、DB2 ストアード・プロシージャーの呼び出し、または CLP (Command Line Processor) コマンドを使用します。

Visual Studio アドインによる XML シュレッディングのサポートに関する詳細は、「Introduction to annotated XML schema decomposition using the DB2 Visual Studio 2005 Add-in」を参照してください。

XML スキーマにアノテーションを付けるには、DWB (DB2 Developer Workbench) を使うという方法もあります。無料でダウンロードできる DWB は、ストアード・プロシージャーとユーザー定義関数の開発を含め、DB2 データベース・アプリケーションの作成、編集、デバッグ、デプロイ、そしてテストを行うための包括的な環境です。ダウンロード情報については、この記事の終わりにある「ダウンロード」セクションを参照してください。

DWB には、コンポーネントの 1 つとしてアノテーション付き XML スキーマ分解マッピング・エディターがあります。このエディターでは単純かつ直観的なグラフィカル・インターフェースを使って、XML スキーマとリレーショナル・スキーマとの関係をマッピングすることができます。グラフィカル・インターフェースにより XML 要素または属性を DB2 のリレーショナル列にマッピングすると、自動的に XML スキーマ文書にアノテーションが付けられます。XML スキーマを保管した後、XSR に登録すれば、XML 文書を DB2 に分解する用意は完了です。

XML スキーマのアノテーションおよびストアード・プロシージャーの xdbDecompXML 一式についての詳細は、この記事の範囲外なのでここでは説明しません。DB2 9 XML Guide (「参考文献」を参照) に、アノテーション付き XML スキーマ分解の詳細、さらにコンテンツに基づく条件付き分解、そして適用するコンテンツ変換を指定してから挿入するなどの高度な機能について記載されています。XML Extender とその分解用のメソッドについての知識がある方は、developerWorks の記事「From DAD to Annotated XML Schema Decomposition」(Mayank Pradhan 著) でさらに詳しいことを調べてください。

2. XMLTABLE SQL 表関数

XMLTABLE は、XML 文書での XQuery 式を評価して表を返す SQL 表関数です。返される表には、XML をはじめとするあらゆる SQL データ型の列を含められます。XMLTABLE を INSERT 文と組み合わせて使用すると、値を XML 文書内から取得して、さらにリレーショナル表に値を挿入することができます。 これによって、アノテーション付き XML スキーマ分解と同じ機能を実現します。XMLTABLE と INSERT 文との組み合わせは、「Insert-from-XMLTABLE」文と呼ばれることもあります。

この方法は XML シュレッディングを簡単にするだけでなく、XML 文書のフラグメントをリレーショナル表のさまざまな列に保管するのにも理想的です。

以下のステートメントは、XQuery 式を実行し、DATA 列の値を表として返します。それぞれの行には、特定の顧客に関連付けられた都市、州、郵便番号、そして前回の購入日が示されます。


リスト 19. XMLTABLE 関数
                                
SELECT X.CITY, X.STATE, X.ZIP, X.LAST_PURCHASE FROM 
TEAMROOM.XML_CONTENTS, 
    XMLTABLE (XMLNAMESPACES (DEFAULT 'http://www.ibm.com/developerworks'), 
       'db2-fn:xmlcolumn("XML_CONTENTS.DATA")//customer' 
       COLUMNS 
       "CITY"          CHAR(16) PATH './address/city', 
       "STATE"         CHAR(16) PATH './address/state', 
       "ZIP"           CHAR(6)  PATH './address/zip', 
       "LAST_PURCHASE" DATE     PATH './last_purchase') as X

以下は、上記の XQuery の出力例です。


リスト 20. XMLTABLE の出力例
                                
Baton Rouge      LA               77888  03/10/2007
Baton Rouge      LA               14257  01/07/2007
Richmond         VA               78045  01/26/2007
Oklahoma City    OK               71107  04/13/2007
Tallahassee      FL               41720  04/25/2007
Richmond         VA               39591  03/25/2007
Richmond         VA               36522  03/23/2007
Richmond         VA               32230  02/12/2007
Charleston       WV               33015  02/12/2007
Columbia         SC               72647  01/11/2007
Raleigh          NC               11238  04/02/2007
Nashville        TN               21245  01/06/2007
Fankfort         KY               53793  04/18/2007
Austin           TX               35462  03/13/2007
Columbia         SC               68359  01/01/2007
Jackson          MS               25770  01/20/2007
Little Rock      AR               46342  03/10/2007
Tallahassee      FL               54306  01/20/2007
Charleston       WV               44339  02/20/2007
Frankfort        KY               92403  02/27/2007

<etc ........>

適切な SQL タイプを定義した CUSTOMER_INFOS 表が定義されていれば、XML のマーケティング情報 (表形式) から抽出したこの顧客データをさらにリレーショナル表に挿入することもできます。それには、以下のように SELECT 文を INSERT 文でラップします。



リスト 21. 分解した XML データのリレーショナル表への挿入
                                
INSERT INTO TEAMROOM.CUSTOMER_INFOS
SELECT X.CITY, X.STATE, X.ZIP, X.LAST_PURCHASE FROM 
TEAMROOM.XML_CONTENTS, 
    XMLTABLE (XMLNAMESPACES (DEFAULT 'http://www.ibm.com/developerworks'), 
       'db2-fn:xmlcolumn("XML_CONTENTS.DATA")//customer' 
       COLUMNS 
       "CITY" VARCHAR(16)    PATH './address/city', 
       "STATE" CHAR(16)      PATH './address/state', 
       "ZIP" CHAR(6)         PATH './address/zip', 
       "LAST_PURCHASE" DATE  PATH './last_purchase') as X

さらに、Ruby には Ruby Electric XML (REXML) という XML プロセッサーも付属しています。このプロセッサーを使用すれば、XML データのツリー解析とストリーム解析も可能です。詳細については、「参考文献」セクションを参照してください。





上に戻る


Web 2.0 世界の実現

連載第 1 回では、ユーザーが特定のサブジェクトの更新をサブスクライブするための機能を紹介しました。更新が行われると、ユーザーには E メールで通知が届きます。これでは古臭くていかにも 20 世紀的です。Web 2.0 という新しい世界が開けている今、このような通知を自分の好みのリーダーで RSS や Atom フィードとして受信したいと思うユーザーもいるはずです。

DB2 9 pureXML を使用すれば、ユーザーがそれぞれに好むリーダーで簡単にポーリングできるフィードを生成することができます。そのために使うのが、SQL/XML XML パブリッシング関数です。XML パブリッシング関数を使って XML ノードおよび文書を構成すると、リレーショナル・データと XML データの両方を使用することができます。

注: パプリッシング関数は、コンストラクター関数と呼ばれることもあります。

DB2 9 には、以下の XML パブリッシング関数が用意されています。

  • XMLNAMESPACES
  • XMLELEMENT
  • XMLATTRIBUTE
  • XMLFOREST
  • XMLDOCUMENT
  • XMLCONCAT
  • XMLCOMMENT
  • XMLPI
  • XMLTEXT

それでは、対象のサブスクリプションが更新されるとユーザーに通知する Atom フィードを提供してみましょう。ここでは Atom フィードを使いますが、DB2 では RSS フィードを生成することも同じく可能です。目的のフィードに対応する XML スキーマを使ってフィードを構成すればいいだけの話です。


リスト 22. Atom フィード・ストアード・プロシージャー
                                
CREATE PROCEDURE GET_ATOM_FEED (  )
  DYNAMIC RESULT SETS 1
------------------------------------------------------------------------
-- SQL Stored Procedure 
------------------------------------------------------------------------
P1: BEGIN
  -- Declare cursor
  DECLARE cursor1 CURSOR WITH RETURN FOR
    SELECT XMLSERIALIZE(
      XMLDOCUMENT(
        XMLELEMENT (NAME "feed",
          XMLNAMESPACES(DEFAULT 'http://www.w3.org/2005/Atom'),
          XMLCONCAT (
            XMLELEMENT (NAME "id", 'http://localhost:3000/documents'),
            XMLELEMENT (NAME "title", 'Teamroom Documents'),
            XMLELEMENT (NAME "updated", CURRENT TIMESTAMP),
            XMLELEMENT (NAME "link", 
                        XMLATTRIBUTES('http://localhost:3000/documents/atom_feed' 
                        as "href", 'self' as "rel")),
            XMLELEMENT (NAME "author", 
              XMLCONCAT(
                XMLELEMENT (NAME "name", 'TeamRoom'),
                XMLELEMENT (NAME "email", 'teamroom@developerWorks.ibm.com')
              )
            ),
            XMLAGG (
              XMLELEMENT (NAME "entry",
                XMLCONCAT (
                    XMLELEMENT (NAME "title", name),
                    XMLELEMENT (NAME "id", 'http://localhost:3000/documents/show/' 
                               || CHAR(id)),
                    XMLELEMENT (NAME "updated", updated_at),
                    XMLELEMENT (NAME "link", 'http://localhost:3000/documents/show/' 
                               || CHAR(id)),
                    XMLELEMENT (NAME "category", category),
                    XMLELEMENT (NAME "summary", content_type),
                    XMLELEMENT (NAME "content", XMLATTRIBUTES('text' as "type"), content)
                )
              )
            )
          )
        )
      ) 
      AS CLOB INCLUDING XMLDECLARATION
    )
      FROM (SELECT d.id as id, d.name as name, d.content_type as content_type, 
            d.updated_at as updated_at, s.name as category, s.description as content
          FROM DOCUMENTS d, SUBJECTS s 
          WHERE d.subject_id = s.id
          ORDER BY d.updated_at DESC 
          FETCH FIRST 10 ROWS ONLY) 
      AS doc_list;
      
  -- Cursor left open for client application
  OPEN cursor1;
END P1

この機能をストアード・プロシージャーとして提供しているのは、Rails 開発者が Atom フィードの生成についての詳細を気にしなくても済むようにするためです。開発者が以下のようにストアード・プロシージャーを呼び出せばいいだけにしてあります。


リスト 23. Atom フィード・ストアード・プロシージャーの呼び出し
                                
class Document < ActiveRecord::Base
  [...]
  def atom_feed
    feed = Document.find_by_sql("call teamroom.get_atom_feed()")
    content = feed[0].attributes["1"]
    send_data(content,
              :filename => 'TeamRoomFeed.atom',
              :type => 'text/xml',
              :disposition => "inline")
  end
  [...]
end

DB2 XML パブリッシング関数と Atom 配信フォーマット (Atom Syndication Format) のプロトコルの詳細についてはこの記事では触れません。詳しい情報と参考になるリンクについては、「参考文献」 セクションを参照してください。また、ダウンロードできるアプリケーションには、ストアード・プロシージャーや、フィードを作成するためのアプリケーション・コードを含め、Atom フィードの完全な実装が含まれています。




上に戻る


まとめ

DB2 の pureXML では XML データをネイティブ階層フォーマットで保管できます。これにより、DB2 リレーショナル・データベース管理システムに備わったパフォーマンス、スケーラビリティー、信頼性、そして可用性というメリットを提供すると同時に、アプリケーション同士が XML の共通言語で簡単に対話することができます。さらに Ruby on Rails フレームワークの単純さと柔軟性を組み合わせれば、開発者が世界規模の Web 2.0 アプリケーションを素早く簡単にビルド、デプロイ、そして管理することも可能になります。開発オプションには柔軟性があるため、ビジネスのニーズに合わせて情報をリレーショナル・フォーマットから階層フォーマットに移行することができます。データ・フォーマットを変更しても、パフォーマンスが落ちることはありません。使用している最適化技術は同じで、しかも DB2 技術がもたらすバックアップ、復元、そしてスケーラビリティーというその他すべての信頼性と可用性が適用されるからです。

DB2 pureXML はネイティブ XML の生成をサポートするだけでなく、事後解析されたデータをノード・レベルの粒度でディスクに保管します。このため、索引付け (実際の文書ノードの位置) や DB2 のクエリー・エンジンに組み込まれた XQuery および XPath プリミティブを使用することによって、優れたクエリー・パフォーマンスが実現します。そんな DB2 pureXML は、極めて使いやすい XML ライブラリー一式 (REXML、ROXML など) を提供する Ruby on Rails ランタイムにはうってつけの組み合わせであるとともに、XML ベースのデータ・ストアを Web アプリケーションに短時間で統合することを可能にします。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
Team room sample codeTeamroom2.zip10KBHTTP
ダウンロード形式について


参考文献

学ぶために

製品や技術を入手するために

議論するために


著者について

John Chun は、アプリケーション開発およびツールの分野で活躍する DB2 Advanced Support チームのスペシャリストです。IBM DBT Toronto Lab でこれまで 7 年間、Java、C、C++、Perl、REXX、C# をはじめとする各種言語での DB2 アプリケーション問題の解決に取り組んできました。DB2 CLI および OLEDB ドライバー、そして .NET データ・プロバイダー関連の多数のプロジェクトにも参加しています。彼は DB2 認定ソリューション・エキスパート、認定 Websphere アドミニストレーターでもあります。


Christine Law は、IBM Toronto Lab のシニア DB2 スペシャリスト兼 IBM 認定エキスパートです。JDBC、SQLJ、ストアード・プロシージャー、そして組み込みSQL を専門とする彼女は、さまざまなプログラミング言語とスクリプト言語を使った Linux、UNIX、Windows プラットフォームでの広範なアプリケーション開発経験を持っています。最近では、AJAXや Ruby などのオープン・ソース技術にも関心を寄せています。


Salvador は、2002年からカリフォルニア州サンノゼの IBM Silicon Valley Labs で働いています。現在は、DB2 pureXML を含め、IBM のデータ・サーバー製品を対象としたランタイムおよびツール技術に取り組んでいます。


Alex Pitigoi は、IBM Toronto Lab の顧問ソフトウェア・エンジニアです。1998年以来、Web 技術とデータベース管理を専門に、情報管理の分野でのさまざまなソフトウェア開発プロジェクトに携わっています。最近では、SQLModel プロジェクトの開発を指揮しました。この開発は現在、Eclipse Data Tools プロジェクトならびに複数の IBM データ・サーバーで、データベース管理 Web ツールの全体的アーキテクチャーに組み込まれています。彼は DB2 Satellite Administration Center、IBM Express Runtime にも取り組んでおり、DB2 を対象とした最初の Web Tools セットの開発も主導しています。現在重点的に取り組んでいるのは、新しいオープン・ソース技術 (Ruby、Python、PHP) へのIBM データ・サーバー対応化です。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



はいいいえわからない
 


 


12345
不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ