Skip to main content

永続オブジェクトとエクステント

エクステントという用語は、特定の永続クラスのすべてのレコード (ディスク上のレコード) を表します。%PersistentOpens in a new tab クラスには、クラスのエクステントを操作する複数のメソッドが用意されています。

エクステントの概要

InterSystems IRIS® データ・プラットフォームは、従来にない強力な解釈によるオブジェクトテーブル・マッピングを使用します。既定では、特定の永続クラスのエクステントには、すべてのサブクラスのエクステントが含まれます。したがって、以下のようになります。

  • 永続クラス Person にサブクラス Employee がある場合、Person エクステントには、Person のすべてのインスタンスと Employee のすべてのインスタンスが含まれます。

  • クラス Employee のどのインスタンスの場合も、そのインスタンスは Person エクステントおよび Employee エクステントに含まれます。

インデックスは、インデックスが定義されるクラスの全範囲を自動的にカバーします。Person に定義されているインデックスには、Person インスタンスと Employee インスタンスの両方が含まれます。Employee エクステントに定義されているインデックスには、Employee インスタンスだけが含まれます。

サブクラスは、そのスーパークラスで定義されていない追加のプロパティも定義できます。これらは、サブクラスのエクステントでは使用できますが、スーパークラスのエクステントでは使用できません。例えば、Employee エクステントには Department フィールドが含まれますが、これは Person エクステントには含まれません。

前述の点は、InterSystems IRIS では、同じタイプのレコードをすべて取得するクエリを比較的簡単に作成できることを意味します。例えば、すべてのタイプの人々をカウントする場合、Person テーブルに対してクエリを実行できます。従業員のみをカウントする場合、同じクエリを Employee テーブルに対して実行します。

同様に、ID を使用するメソッドは、すべて多様な形態で動作します。つまり、渡された ID 値に応じて、さまざまなタイプのオブジェクトを操作できるということです。

例えば、Sample.Person オブジェクトのエクステントには、Sample.Person のインスタンスと、Sample.Employee のインスタンスが含まれます。Sample.Person クラスの %OpenId() を呼び出すと、結果の OREF は、データベースに保存されている内容に応じて Sample.PersonSample.Employee のどちらかのインスタンスになります。

 // Open person "10"
 Set obj = ##class(Sample.Person).%OpenId(10)

 Write $ClassName(obj),!    // Sample.Person
 

 // Open person "110"
 Set obj = ##class(Sample.Person).%OpenId(110)

 Write $ClassName(obj),!    // Sample.Employee

Sample.Employee クラスの %OpenId() メソッドでは、ID 10 を開こうとしても、オブジェクトが返されません。これは、ID 10 は Sample.Employee のエクステントではないためです。

 // Open employee "10"
 Set obj = ##class(Sample.Employee).%OpenId(10)

 Write $IsObject(obj),!  // 0

 // Open employee "110"
 Set obj = ##class(Sample.Employee).%OpenId(110)

 Write $IsObject(obj),!  // 1

エクステント定義

既定のストレージ・クラス (%Storage.Persistent) を使用するクラスの場合、InterSystems IRIS は、エクステント・マネージャで使用するために登録されているエクステントのエクステント定義とグローバルを管理します。エクステント・マネージャに対するインタフェースには、%ExtentMgr.UtilOpens in a new tab クラスを使用します。この登録プロセスはクラスのコンパイル時に実行されます。

何らかのエラーまたは名前の競合が発生すると、コンパイルに失敗します。以下に例を示します。

ERROR #5564: Storage reference: '^This.App.Global used in 'User.ClassA.cls' 
is already registered for use by 'User.ClassB.cls'

コンパイルを成功させるには競合を解決します。このユーティリティでは、インデックスの名前を変更するか、データのストレージの場所を明確に追加する必要があります。

Note:

グローバル参照を意図的に共有しているクラスがアプリケーションに複数存在する場合は、関連するすべてのクラスの MANAGEDEXTENT0 を指定します (関連するクラスが既定のストレージを使用する場合)。

MANAGEDEXTENT クラス・パラメータの既定値は 1 です。この値では、グローバル名の登録および競合使用のチェックが実行されます。値が 0 の場合には、登録も競合のチェックも実行されません。

別の可能性として、InterSystems IRIS に古いエクステント定義が含まれていることがあります。例えば、クラスを削除しても、既定ではエクステント定義は削除されません。

前述の例を引き続き使用すると、User.ClassA.cls は削除されましたが、そのエクステント定義が残っている可能性があります。この場合の解決策は、以下のコマンドを使用して、古いエクステント定義を削除することです。

set st = ##class(%ExtentMgr.Util).DeleteExtentDefinition("User.ClassA", "cls")

これで、競合することなく、User.ClassB.cls をコンパイルできます。

クラスとそのエクステント定義を削除するには、以下のいずれかの呼び出しを使用します。

  • $SYSTEM.OBJ.Delete(classname,qspec)classname は、削除するクラスです。qspec では、フラグ e または修飾子 /deleteextent を指定します。

  • $SYSTEM.OBJ.DeletePackage(packagename,qspec)packagename は、削除するパッケージです。qspec では、フラグ e または修飾子 /deleteextent を指定します。

  • $SYSTEM.OBJ.DeleteAll(qspec)qspec では、フラグ e または修飾子 /deleteextent を指定します。これにより、ネームスペース内のすべてのクラスが削除されます。

これらの呼び出しは、%SYSTEM.OBJOpens in a new tab クラスのメソッドです。

エクステント・インデックス

エクステント・インデックスは、現在のネームスペースで定義されているすべてのエクステントおよびサブエクステントのインデックスです。クラス・コンパイラは、既定のストレージ・クラス (%Storage.Persistent) を使用する、ローカルでコンパイルされたクラスについてはこのインデックスを保持します。これらのクラスでは、そのネームスペースについて、パッケージ・マッピング、ルーチン・マッピング、またはグローバル・マッピングが変更された場合、InterSystems IRIS は自動的にこのインデックスを再構築します。

ただし、他のネームスペースからマップされたクラスは、クラスのランタイムが元のネームスペースで変更された場合に自動的にインデックスに追加されたり、インデックスから削除されたりすることはありません。代わりに、このような変更は、以下のいずれかの呼び出しを使用して、ローカル・ネームスペースのエクステント・インデックスで更新する必要があります。

  • $SYSTEM.OBJ.RebuildExtentIndex(updatemode,lockmode) は、指定されたネームスペースのエクステント・インデックス全体を再構築し、成功または失敗を示すステータス値を返します。updatemode が true の場合、インデックスは削除されず、検出された差異のみがインデックスで更新されます。updatemode が false の場合は、インデックスが削除され、全体が再構築されます。lockmode1 の場合、インデックス構造全体に対して排他ロックが取得されます。値 2 の場合は、そのクラスのインデックス作成中に限り、クラス・ノードに対して個々のロックが取得されます。値 3 の場合は、インデックス構造全体に対して共有ロックが取得されます。要求されたロックを取得できない場合は、呼び出し元にエラーが報告されます。lockmode0 の場合、ロックなしを示します。

  • $SYSTEM.OBJ.RebuildExtentIndexOne(classname,lockmode) は、1 つのクラスのエクステント・インデックスを再構築し、成功または失敗を示すステータス値を返します。このメソッドは、classname によって指定されたクラスのエクステント・インデックスでインデックス・ノードを更新します。lockmode の値は RebuildExtentIndex() の場合と同じですが、値 12、および 3 は、個々のクラス・ノードに対するロックとして解釈されます。

これらの呼び出しは、%SYSTEM.OBJOpens in a new tab クラスのメソッドです。

Extent クエリ

すべての永続クラスには、"Extent" というクラス・クエリが自動的に含まれます。このクラス・クエリは、エクステントに含まれるすべての ID を提示します。

クラス・クエリの使用に関する一般的な情報は、"クラス・クエリの定義と使用" を参照してください。以下の例では、クラス・クエリを使用して、Sample.Person クラスのすべての ID を表示します。

  set query = ##class(%SQL.Statement).%New()
  set qStatus = query.%PrepareClassQuery("Sample.Person","Extent")
  if $$$ISERR(qStatus) {write "%Prepare failed:" do $SYSTEM.Status.DisplayError(qStatus) quit}

  set rset=query.%Execute()
  if (rset.%SQLCODE '= 0) {write "%Execute failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}

  while rset.%Next()
  {
    write rset.%Get("ID"),!
  }
  if (rset.%SQLCODE < 0) {write "%Next failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}

Sample.Person エクステントは、Sample.Person のすべてのインスタンスとそのサブクラスを含みます。これについての説明は、"永続クラスの定義" を参照してください。

"Extent" クエリは、以下の SQL クエリと同等です。

SELECT %ID FROM Sample.Person

これらのいずれの方法でも、返される ID 値の順序には依存できないことに注意してください。この要求を満たすために、他のプロパティ値を使用して順序付けられたインデックスを使用する方が効率的であると InterSystems IRIS が判断する場合があるからです。必要に応じて、ORDER BY %ID 節を SQL クエリに追加できます。

関連項目

FeedbackOpens in a new tab