2.1 トポロジ・データを編集する方法

トポロジを編集する必要がある場合は、PL/SQL APIまたはJava APIを使用します。いずれの場合も、Oracle Spatialではインメモリー・トポロジ・キャッシュ(具体的にはTopoMapオブジェクト)が使用されます。(このオブジェクトの詳細は、「TopoMapオブジェクト」を参照してください。)
  • PL/SQL APIを使用する場合、キャッシュを明示的に作成および使用するか、またはSpatialにキャッシュを自動的に作成および使用させることができます。

  • Java APIを使用する場合、キャッシュを明示的に作成および使用する必要があります。

Spatialにキャッシュを自動的に作成および管理させる方が、自分でキャッシュを作成および使用する場合より実行するステップが少ないため簡単です。ただし、Spatialにキャッシュを作成および管理させるとデータベース・アクティビティおよびディスク・アクセスが増加するため、多くの位相要素を編集する必要がある場合は非効率的です。

2.1.1 TopoMapオブジェクト

TopoMapオブジェクトは、トポロジに関連付けられたインメモリー・キャッシュに関連付けられます。キャッシュを明示的に作成および使用してトポロジを編集する場合、トポロジに関連付けるTopoMapオブジェクトを作成し、そのトポロジのすべてまたは一部をキャッシュにロードし、オブジェクトを編集し、定期的にトポロジを更新してデータベースに変更を書き込み、キャッシュ内の変更をコミットしてキャッシュをクリアする必要があります。

この方法では、Spatialにキャッシュを自動的に作成および使用させる場合より多くのステップが必要ですが、一般的に数百または数千の位相要素に影響を及ぼすほとんどのトポロジ編集セッションでは、処理速度および効率が大幅に向上します。ほとんどの説明および図では、この方法を使用しています。

SDO_TOPO_MAP.LOAD_TOPO_MAPファンクションまたはプロシージャのコール時のallow_updatesパラメータの値によって、TopoMapオブジェクトを更新可能または読取り専用に指定できます。

  • 読取り専用のTopoMapオブジェクトを使用すると、位相要素(プリミティブ)はロードされますが、ロックされません。

  • 更新可能なTopoMapオブジェクトを使用すると、位相要素(プリミティブ)はロードされてからロックされます。更新可能なTopoMapオブジェクトの矩形ウィンドウを指定した場合は、指定したウィンドウ内にある位相要素のみを編集できます。(TopoMapオブジェクトには、ユーザーが直接編集できないロックされた位相要素が含まれる場合もありますが、必要に応じてOracle Spatialによって間接的に変更できます。)

    更新可能なTopoMapオブジェクトの使用時に発生する事柄の詳細は、SDO_TOPO_MAP.LOAD_TOPO_MAPファンクションまたはプロシージャの「使用上のノート」を参照してください。

次のプロシージャによって、更新可能なTopoMapオブジェクトが読取り専用に設定されます。

1回のユーザー・セッションに存在できる更新可能なTopoMapオブジェクトは常に1つのみです。ただし、複数の異なるユーザー・セッションで、同じトポロジに基づいた複数の更新可能なTopoMapオブジェクトを使用することはできます。これには、編集ウィンドウに、他の更新可能なTopoMapオブジェクト内にある位相要素が含まれていないことが条件となります。読取り専用のTopoMapオブジェクトは、複数のユーザー・セッション内およびユーザー・セッション間で複数設定できます。

編集ウィンドウ(SDO_TOPO_MAP.LOAD_TOPO_MAPファンクションまたはプロシージャのコール時に指定)が重ならないかぎり、複数のユーザーが同時に1つのトポロジを編集できます。

2.1.2 トポロジ・パラメータの編集方法の指定

トポロジを編集する多くのSDO_TOPO_MAPパッケージ・ファンクションおよびプロシージャ(SDO_TOPO_MAP.ADD_NODESDO_TOPO_MAP.MOVE_EDGEなど)では、トポロジ名またはNULL値のいずれかを最初のパラメータtopologyに指定して、編集方法を指定します。

  • トポロジ名を指定した場合、Spatialによってユーザー・セッションに更新可能なTopoMapオブジェクトが存在するかどうかが確認され、更新可能なTopoMapオブジェクトが存在しない場合、Spatialは内部TopoMapオブジェクトを作成し、そのキャッシュを使用して編集操作を実行し、変更をコミットして(または、例外が発生した場合は、処理の開始時点のセーブポイントまで変更をロールバックして)TopoMapオブジェクトを削除します。(更新可能なTopoMapオブジェクトがすでに存在する場合、例外が発生します。)たとえば、次の文ではMY_TOPOトポロジから、ノードID値が99のノードが削除されます。

    CALL SDO_TOPO_MAP.REMOVE_NODE('MY_TOPO', 99);
    
  • NULL値を指定した場合、Spatialによってユーザー・セッションに更新可能なTopoMapオブジェクトが存在するかどうかが確認され、更新可能なTopoMapオブジェクトが存在する場合、SpatialはTopoMapオブジェクトのキャッシュで操作を実行します。(更新可能なTopoMapオブジェクトが存在しない場合、例外が発生します。)たとえば、次の文では、現行の更新可能なTopoMapオブジェクトから、ノードID値が99のノードが削除されます。

    CALL SDO_TOPO_MAP.REMOVE_NODE(null, 99);

2.1.3 GET_xxxトポロジ・ファンクションの使用

トポロジの情報を取得するSDO_TOPO_MAPパッケージ・ファンクションには、最初の2つのパラメータとしてtopologyおよびtopo_mapを取るものがあります。このようなファンクションには、SDO_TOPO_MAP.GET_EDGE_COORDSSDO_TOPO_MAP.GET_NODE_STARなどがあります。これらのファンクションを使用するには、次のように一方のパラメータに有効な値を指定し、もう一方のパラメータにNULL値を指定します。

  • topologyパラメータに有効な値を指定した場合、Spatialによって指定したトポロジの情報が取得されます。Spatialは内部TopoMapオブジェクトを作成し、そのキャッシュを使用して操作を実行し、TopoMapオブジェクトを削除します。たとえば、次の文では、CITY_DATAトポロジから、ID値が1のエッジのエッジ座標が戻されます。

    SELECT SDO_TOPO_MAP.GET_EDGE_COORDS('CITY_DATA', null, 1) FROM DUAL;
    
  • topologyパラメータにNULL値を指定し、topo_mapパラメータに有効な値を指定した場合、Spatialによって、指定したTopoMapオブジェクト(更新可能または読取り専用のいずれか)が使用され、指定したトポロジの情報が取得されます。たとえば、次の文では、CITY_DATA_TOPOMAP TopoMapオブジェクトから、ID値が1のエッジのエッジ座標が戻されます。

    SELECT SDO_TOPO_MAP.GET_EDGE_COORDS(null, 'CITY_DATA_TOPOMAP', 1) FROM DUAL;
    
  • topologytopo_mapの両方のパラメータにNULLまたは無効な値を指定した場合、例外が発生します。

トポロジの編集操作の情報を取得するSDO_TOPO_MAPパッケージ・ファンクションには、パラメータを取らないものがあります。このようなファンクションには、SDO_TOPO_MAP.GET_FACE_ADDITIONSSDO_TOPO_MAP.GET_NODE_CHANGESなどがあります。これらのファンクションでは、現行の更新可能なTopoMapオブジェクトが使用されます。更新可能なTopoMapオブジェクトが存在しない場合、例外が発生します。たとえば、次の文では、現行の更新可能なTopoMapオブジェクトに追加されたノードのノードID値を持つSDO_NUMBER_ARRAYオブジェクト(「SDO_EDGE_ARRAY型およびSDO_NUMBER_ARRAY型」を参照)が戻されます。

SELECT SDO_TOPO_MAP.GET_NODE_ADDITIONS FROM DUAL;

2.1.4 キャッシュを明示的に使用した編集処理(PL/SQL API)

図2-1に、PL/SQL APIを使用し、TopoMapオブジェクトおよびそれに関連付けられたキャッシュを明示的に使用して位相要素を編集する処理の推奨手順を示します。

図2-1 TopoMapオブジェクトのキャッシュを使用したトポロジの編集(PL/SQL API)

図2-1の説明が続きます
図2-1「TopoMapオブジェクトのキャッシュを使用したトポロジの編集(PL/SQL API)」の説明

図2-1に示した基本的な手順は次のとおりです。

  1. SDO_TOPO_MAP.CREATE_TOPO_MAPプロシージャを使用してTopoMapオブジェクトを作成します。

    これによって、指定したトポロジに関連付けられたオブジェクトを編集するためのインメモリー・キャッシュが作成されます。

  2. SDO_TOPO_MAP.LOAD_TOPO_MAPファンクションまたはプロシージャを使用して、トポロジ全体または矩形ウィンドウを、トポロジからTopoMapオブジェクトのキャッシュに更新用としてロードします。

    インメモリーRツリー索引が、ロードするエッジおよびフェイスに作成されるように指定できます。これらの索引ではメモリー・リソースがいくらか消費され、索引の作成および定期的な再作成に時間がかかりますが、セッションで多くの位相要素を編集する場合は、これらの索引によってパフォーマンスが大幅に向上します。(また、読取り専用のTopoMapオブジェクトを使用する問合せのパフォーマンスも向上します。)

  3. 様々なトポロジの編集操作(たとえば、1000個のノードの追加)を実行します。

    定期的にSDO_TOPO_MAP.VALIDATE_TOPO_MAPファンクションをコールして、キャッシュを検証します。

    SDO_TOPO_MAP.CREATE_EDGE_INDEXおよびSDO_TOPO_MAP.CREATE_FACE_INDEXプロシージャを使用して、TopoMapオブジェクト内のエッジおよびフェイスの既存のインメモリーRツリー索引を再作成できます。また、索引が存在しない場合は、新しい索引を作成できます。索引のパフォーマンスを最適化するには、位相要素を数多く編集したときに、これらの索引を定期的に再作成する必要があります。

    キャッシュ内の編集を廃棄する場合は、SDO_TOPO_MAP.CLEAR_TOPO_MAPプロシージャをコールします。コミットしていない更新がある場合は、このプロシージャは失敗します。コミットされていない更新が存在しない場合は、このプロシージャによってキャッシュ内のデータがクリアされ、キャッシュが読取り専用に設定されます。

  4. SDO_TOPO_MAP.UPDATE_TOPO_MAPプロシージャをコールして、トポロジを更新します。

  5. トポロジの編集操作が終了するまで、必要に応じてステップ3および4 (オブジェクトの編集、キャッシュの検証、Rツリー索引の再作成およびトポロジの更新)を繰り返します。

  6. SDO_TOPO_MAP.COMMIT_TOPO_MAPプロシージャをコールして、トポロジの変更をコミットします。(SDO_TOPO_MAP.COMMIT_TOPO_MAPプロシージャによって、変更のコミット前に、SDO_TOPO_MAP.UPDATE_TOPO_MAPプロシージャの操作が自動的に実行されます。)コミット操作後、キャッシュは読取り専用(更新不可)になります。ただし、同じTopoMapオブジェクトを使用して追加の編集操作を実行する場合、そのオブジェクトを再びロードして使用できます(必要に応じてキャッシュをクリアしてから、ステップ2から5を繰り返します)。

    追加の編集操作を実行するには、SDO_TOPO_MAP.CLEAR_TOPO_MAPプロシージャをコールしてTopoMapオブジェクトのキャッシュをクリアして、ステップ2に戻ります。

    SDO_TOPO_MAP.ROLLBACK_TOPO_MAPプロシージャをコールすると、コミットされていないすべてのトポロジの変更をいつでも廃棄できます。ロールバック操作後、キャッシュがクリアされます。

  7. SDO_TOPO_MAP.DROP_TOPO_MAPプロシージャをコールして、TopoMapオブジェクトを削除します。

    このプロシージャによって、TopoMapオブジェクトが削除され、そのオブジェクトが使用していたすべてのリソースが解放されます。(TopoMapオブジェクトを削除しなかった場合、ユーザー・セッションの終了時にそのオブジェクトが自動的に削除されます。)また、コミットされていないキャッシュ内のトポロジの変更がロールバックされます。

    アプリケーションが異常終了した場合、データベースにコミットされていないすべての変更は廃棄されます。

非常に多くのトポロジの編集操作を実行する予定の場合、それらの操作を複数の編集セッションに分割できます。各セッションで、前述のステップ1から7を実行します。

2.1.5 Java APIを使用した編集処理

図2-2に、クライアント側のJava APIを使用して位相要素を編集する処理の推奨手順を示します。Java APIの概要は、「トポロジ・データ・モデルのJavaインタフェース」およびJavadoc生成のドキュメントを参照してください。Java APIでは、TopoMapオブジェクトとそれに関連付けられたキャッシュを作成および管理する必要があります。

図2-2 TopoMapオブジェクトのキャッシュを使用したトポロジの編集(Java API)

図2-2の説明が続きます
図2-2「TopoMapオブジェクトのキャッシュを使用したトポロジの編集(Java API)」の説明

図2-2に示した基本的な手順は次のとおりです。

  1. TopoMapクラスのコンストラクタを使用してトポロジとデータベースの接続を指定し、TopoMapオブジェクトを作成します。

    これによって、指定したトポロジに関連付けられたオブジェクトを編集するためのインメモリー・キャッシュが作成されます。

  2. TopoMapクラスのloadTopologyまたはloadWindowメソッドを使用して、トポロジ全体または矩形ウィンドウを、トポロジからTopoMapオブジェクトのキャッシュに更新用にロードします。

    インメモリーRツリー索引が、影響を受けるエッジおよびエッジのフェイスに作成されるように指定できます。これらの索引ではメモリー・リソースがいくらか消費され、索引の作成および定期的な再作成に時間がかかりますが、データベース接続中に多くの位相要素を編集する場合は、これらの索引によってパフォーマンスが大幅に向上します。

  3. 様々なトポロジの編集操作(たとえば、1000個のノードの追加)を実行し、TopoMapクラスのupdateTopologyメソッドをコールしてトポロジを更新します。

    定期的にTopoMapクラスのvalidateCacheメソッドをコールして、キャッシュを検証します。

    TopoMapオブジェクトのロード時(ステップ2)にインメモリーRツリー索引を作成した場合、TopoMapクラスのcreateEdgeIndexおよびcreateFaceIndexメソッドをコールして、索引を定期的に(たとえば、100個のノードを追加するたびに)再作成できます。索引のパフォーマンスを最適化するには、位相要素を数多く編集したときに、これらの索引を定期的に再作成する必要があります。

    トポロジを更新せずに、最終更新以降に実行したキャッシュ内の編集操作を廃棄する場合、TopoMapクラスのclearCacheメソッドをコールします。コミットしていない更新がある場合は、clearCacheメソッドは失敗します。コミットされていない更新が存在しない場合は、このメソッドによってキャッシュ内のデータが消去され、キャッシュが読取り専用に設定されます。

  4. TopoMapクラスのupdateTopologyメソッドをコールして、トポロジを更新します。

  5. トポロジの編集操作が終了するまで、必要に応じてステップ3および4 (オブジェクトの編集、キャッシュの検証、Rツリー索引の再作成およびトポロジの更新)を繰り返します。

  6. TopoMapクラスのcommitDBメソッドをコールして、トポロジの変更をコミットします。(commitDBメソッドによって、変更のコミット前に、updateTopologyメソッドが自動的にコールされます。)コミット操作後、キャッシュは読取り専用(更新不可)になります。ただし、同じTopoMapオブジェクトを使用して追加の編集操作を実行する場合、そのオブジェクトを再びロードして使用できます(必要に応じてキャッシュをクリアしてから、ステップ2から5を繰り返します)。

    追加の編集操作を実行するには、TopoMapクラスのclearCacheメソッドをコールしてTopoMapオブジェクトのキャッシュをクリアして、ステップ2に戻ります。

    TopoMapクラスのrollbackDBメソッドをコールすると、コミットされていないすべてのトポロジの変更をいつでも廃棄できます。ロールバック操作後、キャッシュがクリアされます。

  7. TopoMapオブジェクトをNULLに設定してTopoMapオブジェクトを削除します。これにより、そのオブジェクトに対してガベージ・コレクションが実行可能となり、そのオブジェクトが使用していたすべてのリソースが解放されます。(TopoMapオブジェクトを削除しなかった場合、アプリケーションの終了時にそのオブジェクトに対するガベージ・コレクションが自動的に実行されます。)

    アプリケーションが異常終了した場合、データベースにコミットされていないすべての変更は廃棄されます。

非常に多くのトポロジの編集操作を実行する予定の場合、それらの操作を複数の編集セッションに分割できます。各セッションで、前述のステップ1から7を実行します。

2.1.6 トポロジの編集のエラー処理

この項では、次の状況について説明します。

2.1.6.1 入力パラメータのエラー

PL/SQLサブプログラムSDO_TOPO_MAPまたはJavaクラスTopoMapのパブリック・メソッドをコールすると、入力パラメータの値が検証され、TopoMapオブジェクトが使用または作成されて編集または読取り専用操作が実行されます。入力エラーがあった場合、oracle.spatial.topo.TopoDataException例外がスローされます。基礎となるTopoMapオブジェクトで操作が実行される際に、別のエラーが発生する場合があります。

SQLまたはPL/SQLからメソッドをコールすると、次のエラー・メッセージが表示されます。

ORA-29532: Java call terminated by uncaught Java exception:
<specific error message text>

次のPL/SQLの例では、TopoDataException例外を処理する方法を示します。

DECLARE
  topo_data_error EXCEPTION;
  PRAGMA EXCEPTION_INIT(topo_data_error, -29532);
BEGIN
  sdo_topo_map.create_topo_map(null, null, 100, 100, 100);
EXCEPTION
  WHEN topo_data_error THEN
    DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;/
 

前述の例の出力を次に示します。

ORA-29532: Java call terminated by uncaught Java exception:oracle.spatial.topo.TopoDataException: invalid TopoMap name

2.1.6.2 すべての例外

PL/SQLサブプログラムSDO_TOPO_MAPまたはそれらに関連付けられたJavaクラスTopoMap内のメソッド(SDO_TOPO_MAP.ADD_EDGE(addEdge)、SDO_TOPO_MAP.ADD_ISOLATED_NODE(addIsolatedNode)、SDO_TOPO_MAP.ADD_LOOP(addLoop)、SDO_TOPO_MAP.ADD_NODE(addNode)、SDO_TOPO_MAP.ADD_POINT_GEOMETRY(addPointGeometry)、SDO_TOPO_MAP.ADD_POLYGON_GEOMETRY(addPolygonGeometry)、SDO_TOPO_MAP.CHANGE_EDGE_COORDS(changeEdgeCoords)、SDO_TOPO_MAP.MOVE_ISOLATED_NODE(moveIsolatedNode)、SDO_TOPO_MAP.MOVE_NODE(moveNode)、SDO_TOPO_MAP.MOVE_EDGE (moveEdge)、SDO_TOPO_MAP.REMOVE_EDGE (removeEdge)、SDO_TOPO_MAP.REMOVE_NODE (removeNode)およびSDO_TOPO_MAP.UPDATE_TOPO_MAP(updateTopology))のコール時に例外が発生すると、次の操作が自動的に実行されます。

  • トランザクションがロールバックされます。

  • TopoMapオブジェクトのキャッシュがクリアされます。

  • TopoMapオブジェクトが読取り専用になります。