Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

データ・コネクタの定義

この章では、データ・コネクタを定義する方法を説明します。以下のトピックについて説明します。

データ・コネクタの概要

データ・コネクタは、キューブのソースとして、詳細なリストで、またはそれらの両方で使用可能なオブジェクトに、任意の SQL SELECT クエリの結果をマップします。(キューブおよびリストの定義の詳細は、"DeepSee モデルの定義" を参照してください。)

SQL クエリでは、以下の項目の組み合わせを使用できます。

  • DeepSee を使用しているネームスペース内のローカル・テーブル。

  • 同じネームスペース内のビュー。

  • 同じネームスペース内のリンクされたテーブル。リンク・テーブル・ウィザードを使用して、リンクされたテーブルを定義します。このテーブルは、ネームスペース内にクラス定義を持ちますが、外部データベース内のテーブルにリンクされています。

    Important:

    リンクされたテーブルを使用する際に、クエリで制約はありません。"Caché SQL の使用法" の “Caché SQL ゲートウェイの使用法” の章の “SQL ゲートウェイ・クエリに関する制限事項” を参照してください。

データ・コネクタに基づくキューブでは、そのキューブ内のすべてのリストもデータ・コネクタに基づく必要があります。

キューブの更新をサポートするように、データ・コネクタを定義できます。このキューブを更新するには、キューブ全体をリビルドするか、ProcessFact() を使用する必要があります。“キューブの最新状態の維持” を参照してください。

基本データ・コネクタの定義

データ・コネクタを定義するには、以下のようにクラスを作成します。

  • %DeepSee.DataConnectorOpens in a new tab を拡張する必要があります。

  • クエリを指定する必要があります。クエリは、最初のサブセクションで説明するように、XData ブロックで指定できます。

    また、実行時にクエリを作成するコールバックを実装するという方法もあります。これについては、この章で後述します。

  • 2 番目のサブセクションで説明するように、クエリの列をプロパティにマップする出力仕様を定義する必要があります。

  • このデータ・コネクタをリストに使用する必要がある場合、そのクラスでは SUPPORTSIDLIST クラス・パラメータに 1 を指定する必要があります。

    Parameter SUPPORTSIDLIST = 1;
  • このデータ・コネクタをキューブに使用する必要があり、キューブの更新をサポートする予定がある場合、そのクラスでは SUPPORTSSINGLE パラメータに 1 を指定する必要があります。

    Parameter SUPPORTSSINGLE = 1;

データ・コネクタをコンパイルすると、packagename.classname.ResultSet という名前のクラスが生成されます (packagename.classname はデータ・コネクタ・クラス自体の完全名です)。生成されたクラスを編集しないでください。

XData ブロックでのクエリの定義

XData ブロックでクエリを定義するには、以下のように、データ・コネクタ・クラスに要素を追加します。

XData SourceQuery [ XMLNamespace = "http://www.intersystems.com/deepsee/connector/query" ] 
{ 
   <sql>SELECT %ID, DateOfSale, Product->Name AS ProductName FROM HoleFoods.SalesTransaction</sql> 
}

メモ :

  • データ・コネクタが詳細リストまたは更新をサポートする必要がある場合は、この方法を使用できません。その場合は、代わりに、この章で後述する “実行時におけるクエリの定義” を参照してください。

  • この XData ブロックの名前は必ず SourceQuery とします。

  • XMLNamespace パラメータは、"http://www.intersystems.com/deepsee/connector/query" である必要があります。

  • XData ブロックには、実行する SQL クエリを含む <sql> 要素を 1 つ含める必要があります。

  • クエリは、必要な他のフィールドに加えて、レコードの ID を返す必要があります。

  • 「より小さい」を意味するシンボル (<) をクエリにインクルードするには、&lt; を使用します。

    以下はその例です。

    <sql>SELECT A,B,C FROM MyApp.MyTable WHERE A&lt;'50'</sql>
    

    同様に、アンパサンド (&) をクエリにインクルードするには、&amp; を使用します。

  • このデータ・コネクタをリストに使用している場合や、キューブの更新をサポートする必要がある場合、そのクエリは WHERE $$$RESTRICT トークンで終了する必要があります。以下はその例です。

    <sql>SELECT A,B,C FROM MyApp.MyTable WHERE $$$RESTRICT</sql>

    $$$RESTRICT トークンは大文字と小文字を区別します。

    Note:

    $$$RESTRICT は、マクロではありません。これは、コンパイル時ではなく、実行時に置換されます。

  • Caché の矢印構文を使用してフィールドにアクセスする場合は、フィールドのエイリアスの指定も必要になることがあります。具体的には、データ・コネクタをキューブの基礎として使用する場合やキューブ要素の定義でフィールドを使用する場合に、エイリアスが必要です。

    例えば、以下のクエリを考えてみます。

    SELECT %ID, DateOfSale, Product->Name FROM HoleFoods.SalesTransaction
    

    この場合、キューブ定義が Product->Name フィールドを参照する方法はありません。Product->Name または Product.Name を使用すると、ビルド・プロセスによってエラーがスローされます。したがって、このフィールドはレベルやメジャーの基礎としては使用できません。

    一方で、以下のクエリを考えてみます。

    SELECT %ID, DateOfSale, Product->Name AS ProductName FROM HoleFoods.SalesTransaction
    

    この場合、ProductName はソース・クラスのプロパティとして扱うことができるため、これに基づいてレベルまたはメジャーを定義できます。

出力仕様の定義

以下の例のように、すべてのデータ・コネクタ・クラスに、クエリの列をプロパティにマップする XData ブロックを設定する必要があります。

XData Output [ XMLNamespace = "http://www.intersystems.com/deepsee/connector/output" ]
{
<connector> 
   <property name="Gender" sourceProperty="Gender" /> 
   <property name="Age" sourceProperty="Age" type="%ZEN.Datatype.integer"/>
   <property name="HomeCity" sourceProperty="HomeCity"/>
   <property name="PatientGroup" sourceProperty="PatientGroup" 
             transform='$CASE(%val,"A":"Group A","B":"Group B",:%val)' />
   <property name="TestScore" sourceProperty="TestScore" type="%ZEN.Datatype.integer"/>
</connector>
}

<property> 要素は、データ・コネクタのプロパティであり、DeepSee で使用可能です。

メモ :

  • XData ブロックの名前は必ず Output とします。

  • XMLNamespace パラメータは、"http://www.intersystems.com/deepsee/connector/output" である必要があります。

  • この XData ブロックには、<connector> 要素を 1 つ含める必要があります。

  • <connector> 要素には、1 つ以上の <property> 要素が含まれている必要があります。

  • <property> 要素では、以下の属性の一部またはすべてを指定する必要があります。

    属性 目的
    name プロパティの名前。キューブ内またはキューブのソース式内のソース・プロパティとして、またはリスト内のフィールドとして使用されます。
    sourceProperty 結果セットの対応する列の名前。
    type (オプション) プロパティのデータ型。既定は、%Library.StringOpens in a new tab です。
    transform (オプション) 入力として %val (現在の列値) を使用し、変換後の値を返す式。
  • このデータ・コネクタをリストに使用する場合は、該当する <property> 要素に idkey 属性も指定します。この属性は、指定されたプロパティがデータ・セットの IdKey を表すことを示します。

    idKey="true" で複数のフィールドをマークした場合、データ・コネクタはこれらのフィールドを組み合わせます。

    Note:

    データ・コネクタに基づくキューブでは、そのキューブ内のすべてのリストもデータ・コネクタに基づく必要があります。また、それらのすべてのデータ・コネクタは、idkey="true" としてマークされた同じプロパティを持つ必要があります。これは、基礎となるメカニズムがいずれの場合も同じ ID 値を使用するためです。

以下に、idkey の使用例を示します。

XData Output [ XMLNamespace = " http://www.intersystems.com/deepsee/connector/output" ]
{
<connector >
   <property name= "%ID" sourceProperty ="ID" displayName ="Record ID" idKey= "true"/>
   <property name= "Product" sourceProperty ="Product" displayName ="Product name"/>
   <property name= "AmountOfSale" sourceProperty ="AmountOfSale" displayName ="Amount of sale"/>
</connector >
}

クエリ結果のプレビュー

データ・コネクタをテストするために、クエリ結果を直接表示するには、テスト・ページを使用するか、ターミナルで結果を出力します。

テスト・ページの表示

データ・コネクタのテスト・ページを表示する手順は以下のとおりです。

  1. スタジオでデータ・コネクタ・クラスを開きます。

  2. [ビュー]→[ブラウザで表示] をクリックします。

次のようなページが表示されます。

generated description: data connector test page

ターミナルでの結果の出力

データ・コネクタの結果を簡単に確認するには、ターミナルで %Print() クラス・メソッドを使用します。以下はその例です。

d ##class(DeepSee.Model.PatientsQuery).%Print()
1     1         SUBJ_1003 M         27        Redwood
2     2         SUBJ_1003 M         41        Magnolia
3     3         SUBJ_1003 F         42        Elm Heigh
...

既定では、このメソッドは結果の最初の 100 個のレコードを出力します。

このメソッドには、以下のシグニチャがあります。

classmethod %Print(ByRef pParameters, pMaxRows As %Integer = 100) as %Status

pParameters は現在使用されていません。pMaxRows は表示する行数の最大値です。

実行時におけるクエリの定義

XData ブロックでハードコードされたクエリを定義する代わりに、実行時にクエリを作成できます。データ・コネクタが詳細リストまたは更新をサポートする必要がある場合は、この方法を使用する必要があります。

実行時にクエリを作成するには、%OnGetSourceResultSet() メソッドを実装します。このメソッドには、以下のシグニチャがあります。

Method %OnGetSourceResultSet(ByRef pParameters, Output pResultSet) As %Status

pParameters は現在使用されていません。pResultSet は結果セットです。

実装では、以下の手順を実行します。

  1. このデータ・コネクタを多目的に使用する場合、データ・コネクタのインスタンスの %mode プロパティを調べます。データ・コネクタのインスタンスが作成されると、DeepSee ではこのプロパティを自動的に設定します。このプロパティには、以下の値のいずれかがあります。

    • "all" — キューブが構築されていること、またはすべてのメンバが表示されていることを示します。

    • "idlist" — リストが要求されていることを示します。

    • "single"%ProcessFact() が実行されたことを示します。

  2. %SQL.StatementOpens in a new tab のインスタンスを作成します。クエリは、必要な他のフィールドに加えて、レコードの ID を返す必要があります。

    このデータ・コネクタが作成されたモードに応じて、クエリの詳細は異なります。通常は、以下のとおりです。

    • "all" モードで使用する基本クエリを定義します。

    • モードが "single" の場合、制限を追加し、更新されている単一レコードを取得します。最初のサブセクションで詳細に説明します。

    • モードが "idlist" の場合、別の制限を追加し、レコードのサブセットを取得します。2 番目のサブセクションで詳細に説明します。

  3. 必要に応じて実行時の値にパラメータとして渡し、その文を実行します。以降のサブセクションの説明のとおり、文インスタンスのプロパティとして、特定の実行時の値を使用できます。

    この手順によって、%SQL.StatementResultOpens in a new tab のインスタンスを作成します。

  4. %SQL.StatementResultOpens in a new tab のインスタンスを出力パラメータとして返します。

更新が要求された場合のレコードの制限

ProcessFact() でキューブを更新するときには、更新するレコードの ID を指定します。キューブで使用するためのデータ・コネクタを作成するときには、そのクエリが指定された ID のみを使用するように、ロジックを追加する必要があります。この場合、データ・コネクタの %singleId プロパティを使用できます。このプロパティには、更新対象のレコードの ID が格納されています。以下はその例です。

  //do this when constructing the SQL statement
  if (..%mode="single") {
      set sql = sql _ " where %ID = ?"
   }

...
  //do this when executing the SQL statement
  if (..%mode="single") {
             set pResultSet = tStatement.%Execute(..%singleId) 
  }

ProcessFact() の詳細は、“キューブの最新状態の維持” の章を参照してください。

リストが要求された場合のレコードの制限

ユーザがリストを要求すると、DeepSee は指定のコンテキストで使用されるレコードの ID を取得して、それらの ID を後で使用するために格納します。既定のリストの場合、DeepSee はリストの SQL クエリで、それらの ID を 自動的に使用します。リストで使用するデータ・コネクタを作成するときには、それらの ID をクエリで使用するためのロジックを追加する必要があります。

この場合、DeepSee がリスト用の ID を格納する方法を理解する必要があります。これらの ID はテーブル (このキューブのリスト・テーブル) に書き込まれます。このテーブルには、以下の列が含まれています。

  • _DSqueryKey — リストを識別します。

  • _DSsourceId — 元のソース・データと同じ ID。

以下に例を示します。

generated description: listing table example

ここでは、最初の 5 行が _DSsourceId 列で得られる 5 つのレコードの ID を使用する、リスト 83616140 に関連付けられています。それに続く 2 行が 2 つのレコードの ID を使用する、リスト 2139316107 に関連付けられています。

リスト・テーブルを使用するようにデータ・コネクタ・クエリを変更する方法は 2 つあります。

  • クエリに IN 節を追加して、サブクエリ内でリスト・テーブルの該当する行を使用します。以下に例を示します。

    SELECT A,B,C FROM MyApp.MyTable
    WHERE (ID IN (SELECT _DSsourceId FROM listingtable WHERE
    _DSqueryKey=somekey))

    この場合は以下のようになります。

    • listingtable は、キューブのリスト・テーブル名です。このテーブル名を取得するには、データ・コネクタの %listingTable プロパティを使用します。

    • somekey は、現在のリストの一意キーです。このキーを取得するには、データ・コネクタの %listingKey プロパティを使用します。

    この方法では、<MAXSTRING> エラーなどのサイズに関連する問題が発生することがあります。

  • 適切な WHERE 節を使用して、ソース・テーブルとリスト・テーブル間で JOIN を実行します。

キューブのソースおよびリストのソースとして使用されるデータ・コネクタの例を以下に示します。リストのキーがパラメータとしてクエリに渡されていることに注意してください。

Method %OnGetSourceResultSet(ByRef pParameters, Output pResultSet) As %Status
{
  set tSC = $$$OK
  set pResultSet = ""
  Try {
      set sql = "SELECT %ID, fdate, fname, ftimestamp FROM TestTD.TimeDimensions"
      //when we're using this for a listing, add WHERE clause to restrict to
      //the appropriate IDs (in the table given by the %listingTable property)
      
      if (..%mode="idlist") {
          set sql = sql _ " where %ID in (select _DSsourceId from " 
                      _ ..%listingTable _ " where _DSqueryKey = ?)"
      }
      
      set tStatement = ##class(%SQL.Statement).%New()
      set tSC = tStatement.%Prepare(.sql)

      If $$$ISERR(tSC) {
          set ex = ##class(%Exception.StatusException).CreateFromStatus(tSC)
          throw ex
      }
      
      //if we're using this for a listing, pass in the listing key as a parameter
      if (..%mode="idlist") {
          set pResultSet = tStatement.%Execute(..%listingKey)
      } else {
          set pResultSet = tStatement.%Execute()
      }
      
      //check %SQLCODE and report if there's an error
      If pResultSet.%SQLCODE {
          set sqlcode=pResultSet.%SQLCODE
          set message=pResultSet.%Message
          set ex = ##class(%Exception.SQL).CreateFromSQLCODE(sqlcode, message)
          throw ex
          } 
  }
  Catch(ex) {
      Set tSC = ex.AsStatus()
  }
  Quit tSC
}

その他のコールバック

%DeepSee.DataConnectorOpens in a new tab クラスには、エラーの処理、行での変換の実行、フィルタ処理の実行などを行うようにカスタマイズできる追加のコールバック・メソッドが用意されています。これらには %OnNextRecord() および %OnProcessRecord() があります。詳細は、"インターシステムズ・クラス・リファレンス" を参照してください。

プログラムによるデータ・コネクタの使用

プログラムを使用してデータ・コネクタを使用するには、以下の手順を実行します。

  1. データ・コネクタのインスタンスを作成します。

  2. 結果セットを返すその %Execute() メソッドを呼び出します。このメソッドは、参照によってステータスも返します。

  3. 返されたステータスをチェックします。

  4. ステータスがエラーでなければ、その結果セットを使用できます。これは、%SQL.StatementResultOpens in a new tab のインスタンスです。

以下はその例です。

    Set tConnector=..%New()
    Set tRS=tConnector.%Execute(,.tSC)
    If $$$ISERR(tSC) {Quit}
    //use tRS as needed ...
FeedbackOpens in a new tab