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?

永続クラスのその他のオプション

この章では、永続クラスに使用できる、その他のオプションについて説明します。以下のトピックについて説明します。

永続オブジェクトの概要” の章、“永続オブジェクトを使用した作業” の章、“永続クラスの定義” の章、および付録 “オブジェクト同期化機能の使用法” も参照してください。

このドキュメントをオンラインで表示している場合は、このドキュメントの "序文" を使用すると、他のトピックをすばやく見つけることができます。

読み取り専用クラスの定義

オブジェクトを開くことはできても、保存または削除できない永続クラスを定義できます。これを行うには、クラスの READONLY パラメータを 1 に設定します。

Parameter READONLY = 1;

これは、既存のストレージ (既存のグローバルや外部データベースなど) にマップされたオブジェクトを持っている場合にのみ便利です。読み取り専用オブジェクトで %Save() メソッドを呼び出す場合、常にエラー・コードが返されます。

インデックスの追加

インデックスは、永続クラスのインスタンス全体にわたる検索を最適化するためのメカニズムを提供します。インデックスは、クラスに関連付けられた一般的に要求されるデータのサブセットを定義します。これらは、パフォーマンス・クリティカルな検索のオーバーヘッドを削減するのに非常に役立ちます。

インデックスは、インデックスが定義されるクラスの全範囲を自動的にカバーします。Person クラスがサブクラス Student を持つ場合、Person で定義されたすべてのインデックスは、Person オブジェクトと Student オブジェクトの両方を含みます。Student クラスで定義されたインデックスは、Student オブジェクトだけを含みます。

インデックスは、それらのクラスに属する 1 つ、または複数のプロパティで並べ替えできます。これは、返される結果の順序を制御するのに大変便利です。

またインデックスは、並べ替えされたプロパティに基づいて、クエリで頻繁に要求される他のデータを格納できます。インデックスの一部として他のデータを含めることによって、インデックスを使用するクエリの性能が大きく向上します。メイン・データ・ストレージにアクセスしなくても、クエリがインデックスを使用して結果セットを生成できます。(以下の Data キーワードを参照してください。)

インデックスの詳細は、"Caché SQL 最適化ガイド" の “インデックスの定義と構築” の章を参照してください。特に、“インデックスを付けることができるプロパティ” のセクションが役立ちます。"Caché クラス定義リファレンス" の “インデックス定義” も参照してください。

外部キーの追加

対応する永続クラスの外部キーを定義して、テーブル間の参照整合性を強制できます。外部キー制約を持つテーブルを変更する際に、外部キー制約が確認されます。外部キーを追加する方法の 1 つは、クラス間にリレーションシップを追加することです。“リレーションシップの定義と使用” の章を参照してください。クラスには、明示的な外部キーも追加できます。詳細は、"Caché SQL の使用法" の “外部キーの使用法” を参照してください。完全なリストについては、"Caché クラス定義リファレンス" の “外部キー定義” を参照してください。

トリガの追加

Caché SQL はトリガの使用をサポートしているので、永続クラスに関係するすべてのトリガは、クラスの SQL プロジェクションの一部として含まれています。

トリガは、特定のイベントが Caché SQL で発生するときに実行されるコード・セグメントです。Caché は INSERT コマンド、UPDATE コマンド、DELETE コマンドの実行をベースにしたトリガをサポートします。トリガ定義により、指定されたコードは関連するコマンドが実行される直前、または直後に実行されます。各イベントは、実行順序が指定されていれば複数のトリガを持つことができます。

Foreach = row/object を使用してトリガが定義されている場合、トリガはオブジェクト・アクセスの特定の時点でも呼び出されます。"Caché SQL の使用法" の “トリガの使用法” にある “トリガとトランザクション” を参照してください。

トリガは、従来のストレージ・クラス %CacheSQLStorageOpens in a new tab によって使用されていた永続メソッドによっても呼び出されます。これは、永続の動作を内部的に実装するために SQL 文を使用しているためです。

トリガの詳細は、"Caché SQL の使用" の “トリガ” を参照してください。"Caché クラス定義リファレンス" の “トリガ定義” も参照してください。

ObjectScript からのフィールドの参照

クラス定義内には、SQL で使用される ObjectScript コードを含むことのできる場所が複数あります。例えば、SQL 計算フィールド・コードおよびトリガ・コードは、SQL 内から実行されます。これらの場合、現在のオブジェクトという概念はないので、ドット構文を使用して、特定のインスタンス内のデータにアクセスしたり、データを設定することはできません。代わりに、フィールド構文を使用して現在の行内のフィールドとして同じデータにアクセスできます。

現在の行の特定のフィールドを参照するには、{fieldname} 構文を使用します (fieldname は、フィールド名です)。

例えば、以下のコードは、従業員の給与が、50000 未満かどうかを確認します。

 If {Salary} < 50000 {
    // actions here...
 }
Note:

UPDATE トリガ・コードでは、{fieldname} は、更新済みのフィールド値を示します。DELETE トリガ・コードでは、{fieldname} は、ディスク上のフィールドの値を示します。

SQL 計算フィールドの現在のフィールドを参照するには、{*} 構文を使用します。

例えば、以下のコードは、Compensation フィールドのための計算コードに表示され、Salary フィールドおよび Commission フィールドの値に基づいてその値を計算します。

 Set {*} = {Salary} + {Commission}

トリガ固有の構文については、"Caché SQL の使用法" の “トリガの定義” の章の “特殊なトリガ構文” のセクションを参照してください。

行レベル・セキュリティの追加

一般的なセキュリティに加えて、Caché では 1 行ごとのきめ細かい SQL セキュリティを提供します。これは、行レベル・セキュリティと呼ばれます。行レベル・セキュリティでは、各行に、表示操作を承認されたユーザまたはロールのリストが保持されます。ユーザおよびロールの詳細は、"Caché セキュリティ管理ガイド" の “ユーザ” および “ロール” の章を参照してください。

通常、SQL セキュリティは、テーブルまたはビューに対してユーザまたはロールに SELECT 特権を許可することによって制御します。ロールを使用することにより、セキュリティ・ロールの数がユーザの数を大幅に下回る場合にアクセス制御が単純化します。ほとんどの場合、各ユーザがどの行を選択できるかを制御するのにはビューレベル・セキュリティで十分です。ただし、目的の制御を実現するのに必要なビューの数が非常に多くなる場合は、きめ細かいアクセス制御を行うために別の方法が必要となります。

例えば、病院では各患者が患者固有のデータをオンラインで入手できるようにする場合があります。各患者に個別のビューを作成する方法は、実用的ではありません。代わりに、きめ細かいアクセス制御と Caché のロールベースの認証モデルを組み合わせることにより、行レベル・セキュリティでこのタイプのアプリケーションを効率的に、より安全に作成できます。

以下は、行レベル・セキュリティの使用に関する制約です。

  • 行レベル・セキュリティは、永続クラスでのみ利用可能です。

  • 行レベル・セキュリティは、Caché サーバ上でインスタンス化されたテーブルでのみ利用可能です。リンク・テーブル (つまり、外部サーバ上でインスタンス化されたテーブル) では利用できません。

  • 行レベル・セキュリティは、SQL から行にアクセスする際にのみ適用されます。グローバルに直接アクセスする場合、またはオブジェクト・インタフェースを介してグローバルにアクセスする場合には適用されません。

行レベル・セキュリティの設定

テーブルの行レベル・セキュリティを有効にするには、そのテーブルの投影元のクラスの定義を編集します。その方法を以下に示します。

  1. スタジオの [クラス] メニューで [オーバーライド] を選択します。表示されたダイアログの [パラメータ] タブで ROWLEVELSECURITY パラメータを選択します。

  2. クラス定義コードでは、ROWLEVELSECURITY の値を 1 に設定します。以下は、その例です。

    ROWLEVELSECURITY = 1;
    

    このパラメータの定義は、行レベル・セキュリティが有効であり、このクラスは生成された %READERLIST プロパティを使用して、行へのアクセスが認証されたユーザおよびロールについての情報を格納することを示しています。

    または、パラメータを以下のように定義できます。

    ROWLEVELSECURITY = rlsprop;
    

    rlsprop は、同じクラス内のプロパティ名です。この代替手段では、行レベル・セキュリティが有効であり、クラスは指定されたプロパティを使用して、行へのアクセスが認証されたユーザおよびロールに関する情報を格納することを示しています。この場合、次のようにインデックスもクラスに追加します。

    Index %RLI On rlsprop;
    
  3. %SecurityPolicy() クラス・メソッドを定義します。このクラス・メソッドは、ビューおよびテーブルの SELECT 特権を前提とし、行の選択を許可されているロールおよびユーザ名を指定します。

    %SecurityPolicy() メソッドの構造は以下のとおりです。

    ClassMethod %SecurityPolicy() As %String [ SqlProc ]
    {
        QUIT ""
    }
    

    その特性は以下のとおりです。

    • “%SecurityPolicy” という名前のクラスメソッドです。

    • 文字列 (タイプ %String) を返します。

    • ゼロ個以上の引数を指定できます。このメソッドに引数がある場合は、各引数がクラス内のプロパティ名と一致する必要があり、すべて互いに異なる必要があります。

    • SqlProc キーワードは、メソッドをストアド・プロシージャとして呼び出すことができることを示します。

    • メソッドの QUIT 文は、行を表示できるユーザまたはロールを返します。複数のユーザまたはロールがある場合、QUIT はそれらの名前をコンマ区切りリストにして返す必要があります。例に示すように、Null 文字列を返す場合は、テーブルで SELECT 特権を持つすべてのユーザが行を表示できることを示します。

    Important:

    %All ロールに割り当てられたユーザには、行レベル・セキュリティによって保護されているテーブルの行に対するアクセス権が自動的には付与されません。%All ユーザがこれらの行にアクセスできるようにするには、%SecurityPolicy() メソッドで明示的にそのアクセス権の付与を指定する必要があります。

  4. クラスおよび依存クラス (存在する場合) をコンパイルします。

既存のデータを含むテーブルへの行レベル・セキュリティの追加

行レベル・セキュリティを既存のデータを含むテーブルに追加するには、まず、前述の “行レベル・セキュリティの設定” で説明する手順を実行します。次に、以下の操作を行います。

  1. テーブルのインデックスを再構築します。

  2. 各行を表示できるユーザおよびロールを一覧表示するプロパティの値を更新します。

インデックスの再構築

Caution:

ユーザがこのテーブルのデータにアクセスしている間は、インデックスを再構築しないでください。これを行うと、クエリ結果が不正確になる場合があります。

テーブルのインデックスを再構築するための手順は、以下のようになります。

  1. WITH CHECK OPTION 節を持つ定義済みのビューがテーブルにある場合は、DROP VIEW コマンドを使用してこれらのビューを削除します (各行にどのユーザがアクセス権を持つかという設定を更新した後、これらのビューを再作成できます)。

  2. 管理ポータルの [SQL] ページに移動し (システム, SQL)、そのテーブルを含むネームスペースを選択します。

  3. [SQLスキーマを参照] を選択します。システム, SQL, スキーマ ページが表示されます。

  4. [スキーマ] ページの変更したテーブルを含むパッケージの行で、[テーブル] を選択すると、その [テーブル] ページが表示されます。

  5. その [テーブル] ページで、[名前] 列にあるテーブルの名前を選択すると、その [テーブル属性] ページが表示されます。

  6. [テーブル属性] ページで [インデックス再構築] を選択して、インデックスを再構築します。

各行を表示できるユーザおよびロールの更新

これを実行する手順は以下のとおりです。

  1. 管理ポータルのホーム・ページで、[SQLクエリ実行] ページ (システム, SQL, SQLクエリ実行) に移動します。

  2. テーブルを含むネームスペースを選択します。

  3. [SQLクエリ実行] ページの編集可能領域で、テーブルを更新する文を発行します。その形式は以下のようになります。

    UPDATE MySchema.MyClass SET rlsprop = 
                    MySchema.SecurityPolicy(MySQLColumnName1, ...)
    

    各項目の内容は次のとおりです。

    • MySchema は、そのクラスを含むスキーマ (パッケージ) です。

    • MyClass はそのクラスの名前です。

    • rlsprop は、行を読み取ることができるユーザおよびロールのリストを含むフィールドです。これは、既定では %READERLIST であり、それ以外は ROWLEVELSECURITY パラメータの宣言で指定されるプロパティ名です。

    • SecurityPolicy は、%SecurityPolicy() メソッドの定義で SqlName 値により指定される値です。%SecurityPolicy() メソッドに明示的な SQL 名がなく、そのクラスが MySchema.MyClass である場合、既定の名前は myClass_sys_SecurityPolicy (MySchema.MyClass_sys_SecurityPolicy の完全修飾形式) です。

    • MySQLColumnName1, ... は、%SecurityPolicy() クラス・メソッドで定義される、引数に対応する一連の SQL 列名 (存在する場合) です。

  4. [クエリ実行] をクリックします。

  5. 必要に応じて、最初に削除したビューを再作成します。

パフォーマンスのヒントおよび情報

%READERLIST プロパティは計算フィールドであり、その値は %SecurityPolicy() メソッドによって決まります。INSERT または UPDATE が実行されるたびに、その行に対して %SecurityPolicy() が呼び出され、%READERLIST の値が自動的に入力されます。

%READERLIST プロパティのコレクション・インデックスが定義され、これにより、クエリ・オプティマイザで使用されて、行レベル・セキュリティが有効になったときのパフォーマンス上の影響を最小化できます。

通常、セキュリティ・ポリシーは複数のコンマ区切りのロールまたはユーザ名を返す可能性があるため、既定では、ROWLEVELSECURITY を 1 に設定すると、コレクション・インデックスは %READERLIST プロパティ (列) に対して定義されます。セキュリティ・ポリシーが複数のユーザまたはロール名を返すことがない場合は、ROWLEVELSECURITY パラメータをオーバーライドし、%RLI インデックスを通常の (非コレクション) ビットマップ・インデックスとして明示的に定義できます。通常は、これによりパフォーマンスが最適化されます。

セキュリティのヒントおよび情報

行レベル・セキュリティを使用する際は、以下のセキュリティ要素に注意してください。

  • 行レベル・セキュリティは、テーブルレベル・セキュリティに加えて処理を行います。SELECTINSERTUPDATE、または DELETE 文を実行するには、ユーザは該当する行に対してテーブルレベル・アクセスと行レベル・アクセスの両方を許可されている必要があります。

  • ユーザ特権は、実行時 (SQL コマンドの実行を試行する際) に動的に確認されます。

  • 更新可能なビューを作成し、WITH CHECK OPTION を指定した場合、そのビューの INSERT 処理は、挿入される行が、ビューで指定された WHERE 句を満たすかどうかを確認します。さらに、行レベルのセキュリティを持つテーブルからビューを作成している場合、ビューで SELECT * FROM のコマンドを発行した際、ビューの WHERE 句または暗黙の行レベルのセキュリティ述語により行を表示できないと、INSERT は失敗します。

  • 行へアクセスできる場合は、%READERLIST フィールド (または、行を表示できるユーザおよびロールのリストを保持する任意のフィールド) の値を変更できます。これは、行に対する自分自身のアクセス権を直接的または間接的に削除するアクションを実行できることを示します。

  • 行の挿入を試みた際に、その挿入が仮に行レベル・セキュリティが定義されていない状態で UNIQUE 制約に違反するようなものであれば、行レベル・セキュリティが有効なことによりたとえ制約のエラーを引き起こす行が更新トランザクションからは参照できないとしても、行の挿入は制約に違反することになります。

FeedbackOpens in a new tab