データ・コネクタの定義
ここでは、Business Intelligence の実装プロセスの一環として、データ・コネクタを定義する方法を説明します。
データ・コネクタの概要
データ・コネクタは、キューブのソースとして、詳細なリストで、またはそれらの両方で使用可能なオブジェクトに、任意の SQL SELECT クエリの結果をマップします。(キューブおよびリストの定義の詳細は、"InterSystems Business Intelligence のモデルの定義" を参照してください。)
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 を返す必要があります。
-
「より小さい」を意味するシンボル (<) をクエリにインクルードするには、< を使用します。
以下はその例です。
<sql>SELECT A,B,C FROM MyApp.MyTable WHERE A<'50'</sql>
同様に、アンパサンド (&) をクエリにインクルードするには、& を使用します。
-
矢印構文を使用してフィールドにアクセスする場合は、フィールドのエイリアスの指定も必要になることがあります。具体的には、データ・コネクタをキューブの基礎として使用する場合やキューブ要素の定義でフィールドを使用する場合に、エイリアスが必要です。
例えば、以下のクエリを考えてみます。
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> 要素は、データ・コネクタのプロパティであり、Business Intelligence で使用可能です。
メモ :
-
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 >
}
クエリ結果のプレビュー
データ・コネクタをテストするために、クエリ結果を直接表示できます。データ・コネクタの結果を簡単に確認するには、ターミナルで %Print() クラス・メソッドを使用します。以下はその例です。
d ##class(BI.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 は結果セットです。
実装では、以下の手順を実行します。
-
このデータ・コネクタを多目的に使用する場合、データ・コネクタのインスタンスの %mode プロパティを調べます。データ・コネクタのインスタンスが作成されるときに、このプロパティが自動的に設定されます。このプロパティには、以下の値のいずれかがあります。
-
"all" — キューブが構築されていること、またはすべてのメンバが表示されていることを示します。
-
"idlist" — リストが要求されていることを示します。
-
"single" — %ProcessFact() が実行されたことを示します。
-
%SQL.StatementOpens in a new tab のインスタンスを作成します。クエリは、必要な他のフィールドに加えて、レコードの ID を返す必要があります。
このデータ・コネクタが作成されたモードに応じて、クエリの詳細は異なります。通常は、以下のとおりです。
-
"all" モードで使用する基本クエリを定義します。
-
モードが "single" の場合、制限を追加し、更新されている単一レコードを取得します。最初のサブセクションで詳細に説明します。
-
モードが "idlist" の場合、別の制限を追加し、レコードのサブセットを取得します。2 番目のサブセクションで詳細に説明します。
-
必要に応じて実行時の値にパラメータとして渡し、その文を実行します。以降のサブセクションの説明のとおり、文インスタンスのプロパティとして、特定の実行時の値を使用できます。
この手順によって、%SQL.StatementResultOpens in a new tab のインスタンスを作成します。
-
%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() の詳細は、"キューブの最新状態の維持" の項目を参照してください。
リストが要求された場合のレコードの制限
ユーザがリストを要求すると、システムは指定のコンテキストで使用されるレコードの ID を取得して、それらの ID を後で使用するために格納します。既定のリストの場合は、それらの ID がリストの SQL クエリで自動的に使用されます。リストで使用するデータ・コネクタを作成するときには、それらの ID をクエリで使用するためのロジックを追加する必要があります。
この場合、システムがリスト用の ID を格納する方法を理解する必要があります。これらの ID はテーブル (このキューブのリスト・テーブル) に書き込まれます。このテーブルには、以下の列が含まれています。
以下に例を示します。
ここでは、最初の 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))
この場合は以下のようになります。
この方法では、<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() があります。詳細は、"インターシステムズ・クラス・リファレンス" を参照してください。
プログラムによるデータ・コネクタの使用
プログラムを使用してデータ・コネクタを使用するには、以下の手順を実行します。
-
データ・コネクタのインスタンスを作成します。
-
結果セットを返すその %Execute() メソッドを呼び出します。このメソッドは、参照によってステータスも返します。
-
返されたステータスをチェックします。
-
ステータスがエラーでなければ、その結果セットを使用できます。これは、%SQL.StatementResultOpens in a new tab のインスタンスです。
以下はその例です。
Set tConnector=..%New()
Set tRS=tConnector.%Execute(,.tSC)
If $$$ISERR(tSC) {Quit}
//use tRS as needed ...