6.2 トリプルと値のセキュリティ

トリプルと値のセキュリティ・オプションでは、トリプルレベルのセキュリティ・オプションで提供されるラベル・セキュリティのサポートが拡張されて、字句値のセキュリティも包含されています。

このセキュリティ・オプションによって、Oracle AI Databaseによるラベル・セキュリティのネイティブ・サポートの上に、RDF固有の機能の薄いレイヤーが実現されます。トリプルレベル・オプションでサポートされている機能だけでなく、RDFの字句値を一意の数値識別子にマッピングするために使用する内部(values)表にラベル・セキュリティを適用する追加機能もサポートされています。

トリプルと値セキュリティを使用するには、SEM_RDFSA.APPLY_OLS_POLICYプロシージャの実行時に、rdfsa_optionsパラメータ値としてSEM_RDFSA.TRIPLE_AND_VALUESを指定します。たとえば、次のようにします。

EXECUTE sem_rdfsa.apply_ols_policy('defense', SEM_RDFSA.TRIPLE_AND_VALUES,
        network_owner=>‘RDFOWNR’, network_name=>'OLS_NET');

ラベル・セキュリティをRDFトリプルに関連付けるメソッドは、トリプルレベル・セキュリティの項で説明したメソッドと同じであるため、RDFトリプルの(主語、述語、オブジェクト、およびオプションの名前付きグラフ)コンポーネントの字句値にラベル・セキュリティを関連付けるメソッドの概要のみを説明します。

トリプルの個々のコンポーネントに付けるラベルは、互いに独立したもの、およびそのトリプルに付けたラベルとは独立したものにできます。したがって、1つのトリプルに最大5つの異なるラベル(トリプルの個々のコンポーネントに最大4つのラベル、トリプル自体に1つのラベル)を付けることができます。

トリプルと値のセキュリティでは、ラベルが異なる、重複した字句値をvalues表に挿入できます。たとえば、字句値(<urn:Y>など)が、非常に機密性の高いラベル(TOPSECRET)で格納されているとします。ここで、権限が低い(UNCLASSIFIED)ユーザーが次のトリプルを挿入するとします:

<urn:X> <urn:P> <urn:Y> .

TOPSECRET<urn:Y>という字句の値はすでに格納されていますが、権限が低いユーザーには表示されないため、今回はUNCLASSIFIEDのラベルが付いた<urn:Y>が再度格納されます。TOPSECRETのラベルを付けた権限の高いユーザーによる後続の問合せでは、<urn:Y>という字句値の両方のインスタンスが表示されるため、<urn:Y>という字句値の2つのインスタンスが存在することになり、重複した結果行が返されます。字句値の重複に関連する問題を軽減する方法をいくつか次に示します:

  • 重複する字句値の発生の防止または最小化: トリプルを挿入する際に、様々な権限レベルのユーザーが使用すると予想される字句値には最下位のラベルを関連付けます。
  • 問合せ結果からの重複した結果行の排除: 問合せのSELECT句でDISTINCTを使用すると、重複した結果を排除できます。こうすると、重複した字句値の存在に起因していない可能性がある行も含めて、すべての重複した結果行が排除されることに注意してください。

6.2.1 拡張例: RDFデータへのOLSのトリプルと値のセキュリティの適用

この項では、トリプルと値のOracle Label Security (OLS)をRDFデータに適用する方法を説明する拡張例を示します。この例は非常に単純化されており、推奨のプラクティスで使用しているユーザー名およびパスワードをそのまま使用しないでください。

  1. ポリシーおよび関連する管理ユーザーを作成します。

    このステップのコード例は、同じ順序またはわずかに異なる順序で次のアクションを実行します:

    1. データベースでOLSを有効にします。
    2. SYSDBAとして接続し、セキュリティ管理ユーザーfgac_adminおよびdefense_adminを作成します。
    3. LBAC_DBAロールをfgac_adminに付与して、DEFENSE_DBAロールを作成する新しいOLS DEFENSEポリシーを作成できるようにします。
    4. DEFENSE_DBAロールをdefense_adminに付与して、ユーザーがDEFENSEポリシーにラベルを設定できるようにします。
    5. DEFENSEポリシーが適用される可能性があるデータベース・オブジェクトの対象ユーザーに適切なラベルを割り当てます。
    SQL> conn sys/<password_for_sys> as sysdba
    Connected.
    
    SQL> -- enable OLS in the database
    SQL> exec LBACSYS.configure_ols;
    
    PL/SQL procedure successfully completed.
    
    SQL> exec LBACSYS.OLS_ENFORCEMENT.enable_ols;
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- create user for security admin, grant LBAC_DBA role
    SQL> create user fgac_admin identified by <password_for_fgac_admin>;
    
    User created.
    
    SQL> grant connect, unlimited tablespace to fgac_admin;
    
    Grant succeeded.
    
    SQL> grant LBAC_DBA to fgac_admin;
    
    Grant succeeded.
    
    SQL> grant execute on sa_sysdba to fgac_admin;
    
    Grant succeeded.
    
    SQL> 
    SQL> conn fgac_admin/<password_for_fgac_admin>
    Connected.
    SQL> -- create policy DEFENSE, which creates the DEFENSE_DBA role
    SQL> EXECUTE SA_SYSDBA.CREATE_POLICY('DEFENSE','def_label');
    
    PL/SQL procedure successfully completed.
    
    SQL> select column_name from lbacsys.all_sa_policies where policy_name='DEFENSE';
    
    COLUMN_NAME
    ---------------
    DEF_LABEL
    
    1 row selected.
    
    SQL> 
    SQL> conn sys/<password_for_sys>
    Connected.
    SQL> -- create user for policy admin of the DEFENSE policy
    SQL> -- create policy admin user for the DEFENSE policy (created above)
    SQL> create user defense_admin identified by <password_for_defense_admin>;
    
    User created.
    
    SQL> grant connect, unlimited tablespace to defense_admin;
    
    Grant succeeded.
    
    SQL> grant DEFENSE_DBA to defense_admin;
    
    Grant succeeded.
    
    SQL> grant execute on sa_components to defense_admin;
    
    Grant succeeded.
    
    SQL> grant execute on sa_user_admin to defense_admin;
    
    Grant succeeded.
    
    SQL> grant execute on sa_label_admin to defense_admin;
    
    Grant succeeded.
    
    SQL> grant execute on sa_policy_admin to defense_admin;
    
    Grant succeeded.
    
    SQL> 
    SQL> conn defense_admin/<password_for_defense_admin>
    Connected.
    SQL> 
    SQL> BEGIN
      2    ------- create levels -------
      3    SA_COMPONENTS.CREATE_LEVEL('defense',3000,'TS','TOP SECRET');
      4    SA_COMPONENTS.CREATE_LEVEL('defense',2000,'SE','SECRET');
      5    SA_COMPONENTS.CREATE_LEVEL('defense',1000,'UN','UNCLASSIFIED');
      6  
      7    ------ create labels (using the components defined above) -------
      8    SA_LABEL_ADMIN.CREATE_LABEL('defense',1000,'UN');
      9    SA_LABEL_ADMIN.CREATE_LABEL('defense',1500,'SE');
     10    SA_LABEL_ADMIN.CREATE_LABEL('defense',3100,'TS');
     11  
     12    ------ assign default labels to users -------
     13    SA_USER_ADMIN.SET_USER_LABELS('defense', 'RDFOWNR', 'SE');
     14    SA_USER_ADMIN.SET_USER_LABELS('defense', 'A', 'UN');
     15    SA_USER_ADMIN.SET_USER_LABELS('defense', 'B', 'SE');
     16    SA_USER_ADMIN.SET_USER_LABELS('defense', 'C', 'TS');
     17    SA_USER_ADMIN.SET_USER_LABELS('defense', 'Q', 'SE');
     18  END;
     19  /
    
    PL/SQL procedure successfully completed.
  2. RDFネットワーク、RDFグラフを作成し、様々なモードでユーザーと共有します。

    このステップのコード例は、同じ順序またはわずかに異なる順序で次のアクションを実行します:

    1. SYSDBAとして接続し、rdfownrユーザー、およびabcqなど、他の複数のユーザーを作成します。
    2. rdfownrとして接続し、NET1 RDFネットワークを作成します。
    3. RDFネットワーク上の共有アクセス権をabcおよびq (問合せ専用)ユーザーに付与します。
    4. RDFネットワーク上のSA_ONLYアクセス権をdefense_adminユーザーに付与して、このネットワーク上でのみOLSのセキュリティ関連の操作を実行できるようにします。こうしても、RDFネットワークに格納されているデータへのアクセス権は付与されません。
    5. defense_adminとして接続し、RDFネットワークにDEFENSE OLSポリシー(TRIPLE_AND_VALUES)を適用します。
    6. rdfownrとして接続して、PERSONという名前のRDFグラフを作成し、グラフに関するDMLおよび問合せアクセス権をユーザーabcに付与し、問合せ専用アクセス権をユーザーqに付与します。
    SQL> conn sys/<password_for_sys>
    Connected.
    
    SQL> -- create user that can be owner of RDF networks
    SQL> create user rdfownr identified by <password_for_rdfownr>;
    
    User created.
    
    SQL> grant CREATE JOB, connect, resource, unlimited tablespace to rdfownr;
    
    Grant succeeded.
    
    SQL> 
    SQL> --- create general users
    SQL> create user a identified by <password_for_a>;
    
    User created.
    
    SQL> grant connect, unlimited tablespace to a;
    
    Grant succeeded.
    
    SQL> create user b identified by <password_for_b>;
    
    User created.
    
    SQL> grant connect, unlimited tablespace to b;
    
    Grant succeeded.
    
    SQL> create user c identified by <password_for_c>;
    
    User created.
    
    SQL> grant connect, unlimited tablespace to c;
    
    Grant succeeded.
    
    SQL> create user q identified by <password_for_q>;
    
    User created.
    
    SQL> grant connect, unlimited tablespace to q;
    
    Grant succeeded.
    
    SQL> 
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> 
    SQL> -- create an RDF network and enable it for sharing with other users
    SQL> exec sem_apis.create_rdf_network('<tablespace_name>',null,network_owner=>'rdfownr',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> exec sem_apis.enable_network_sharing(network_owner=>'rdfownr',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- grant network access to a few users: full-access (they can create their own graphs) or query-only access
    SQL> EXECUTE sem_apis.enable_network_sharing('RDFOWNR', 'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> BEGIN
      2    sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'A');
      3    sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'B');
      4    sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'C');
      5    sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'Q', options=>' QUERY_ONLY=T ');
      6  END;
      7  /
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- share in SA_ONLY=T mode with policy admin user (note: this sharing mode provides no visibility to RDF data)
    SQL> exec sem_apis.grant_network_access_privs('rdfownr', 'NET1', 'DEFENSE_ADMIN', options=>' SA_ONLY=T ');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- tables in RDF network are not visible to security and policy admin users (EXCEPT when managing security policies on them)
    SQL> conn fgac_admin/<password_for_fgac_admin>
    Connected.
    SQL> select table_name from SYS.all_tables where table_name LIKE 'NET1#RDF%' order by 1;
    
    no rows selected
    
    SQL> conn defense_admin/<password_for_defense_admin>
    Connected.
    SQL> select table_name from SYS.all_tables where table_name LIKE 'NET1#RDF%' order by 1;
    
    no rows selected
    
    SQL> 
    SQL> -- APPLY_OLS_POLICY on the RDF network
    SQL> conn defense_admin/<password_for_defense_admin>
    Connected.
    SQL> exec sem_rdfsa.apply_ols_policy('DEFENSE', sem_rdfsa.TRIPLE_AND_VALUES,network_owner=>'rdfownr',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- after APPLY_OLS_POLICY: a new column gets added to RDF_VALUE$ table and to RDF_LINK$ table
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> select table_name, column_name, data_type from sys.user_tab_columns where table_name IN ('NET1#RDF_VALUE$', 'NET1#RDF_LINK$') and column_name='DEF_LABEL' order by 1;
    
    TABLE_NAME                     COLUMN_NAME     DATA_TYPE
    ------------------------------ --------------- ----------
    NET1#RDF_LINK$                 DEF_LABEL       NUMBER
    NET1#RDF_VALUE$                DEF_LABEL       NUMBER
    
    2 rows selected.
    
    SQL> 
    SQL> -- disable the OLS policy and set the label for all the pre-existing values to the lowest label
    SQL> conn defense_admin/<password_for_defense_admin>
    Connected.
    SQL> exec sem_rdfsa.disable_ols_policy(network_owner=>'rdfownr',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- re-enable the OLS policy and verify that the values are visible to all (EXCEPT security and policy admin users)
    SQL> conn defense_admin/<password_for_defense_admin>
    Connected.
    SQL> exec sem_rdfsa.enable_ols_policy(network_owner=>'rdfownr',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> -- create an RDF graph (owned by rdfownr)
    SQL> exec sem_apis.create_rdf_graph('PERSON',null,null,network_owner=>'rdfownr',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
    
    SQL> -- the corr. RDFT view, used as target for DML operations for this graph, has the extra label column
    SQL> desc NET1#RDFT_PERSON
     Name                                                                                                              Null?    Type
     ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------
     TRIPLE                                                                                                                     MDSYS.SDO_RDF_TRIPLE_S
     DEF_LABEL                                                                                                                  NUMBER
    
    SQL> -- the corr. RDFM view, used as source for query processing for this graph, has the extra column
    SQL> desc NET1#RDFM_PERSON
     Name                                                                                                              Null?    Type
     ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------
     P_VALUE_ID                                                                                                        NOT NULL NUMBER
     START_NODE_ID                                                                                                              NUMBER
     CANON_END_NODE_ID                                                                                                          NUMBER
     END_NODE_ID                                                                                                                NUMBER
     MODEL_ID                                                                                                                   NUMBER
     COST                                                                                                                       NUMBER
     DEF_LABEL                                                                                                                  NUMBER
     CTXT2                                                                                                                      VARCHAR2(4000)
     DISTANCE                                                                                                                   NUMBER
     EXPLAIN                                                                                                                    VARCHAR2(4000)
     PATH                                                                                                                       VARCHAR2(4000)
     G_ID                                                                                                                       NUMBER
     LINK_ID                                                                                                                    VARCHAR2(89)
    
    SQL> 
    SQL> -- share access to the above graph with users who already have shared access to network (Note: user Q is given query-only access)
    SQL> BEGIN
      2    sem_apis.grant_model_access_privs('PERSON','a',sys.odcivarchar2list('INSERT','UPDATE','DELETE','SELECT','QUERY'),network_owner=>'rdfownr',network_name=>'NET1');
      3    sem_apis.grant_model_access_privs('PERSON','b',sys.odcivarchar2list('INSERT','UPDATE','DELETE','SELECT','QUERY'),network_owner=>'rdfownr',network_name=>'NET1');
      4    sem_apis.grant_model_access_privs('PERSON','c',sys.odcivarchar2list('INSERT','UPDATE','DELETE','SELECT','QUERY'),network_owner=>'rdfownr',network_name=>'NET1');
      5    sem_apis.grant_model_access_privs('PERSON','q',sys.odcivarchar2list('QUERY'),network_owner=>'rdfownr',network_name=>'NET1');
      6  END;
      7  /
    
    PL/SQL procedure successfully completed.
  3. 例に使用するユーティリティ関数とビューを設定します。

    次のコードで、ユーティリティ・ビューTRIPLES_VIEWおよびVALUES_VIEWを作成します。これらは、ユーザーが表示できるトリプルと値の簡易ビューを、関連するOLSのラベルとともに返します。特定のidの値が見つからない場合は、id自体が返されますが、先頭にアスタリスクが付きます。

    SQL> -- set up for reporting visibility of triples and values
    SQL> column visible_to_users format a30
    SQL> column subj format a22
    SQL> column pred format a22
    SQL> column obj format a22
    SQL> column labels format a30
    SQL> --
    SQL> create or replace function shortval (val_id number) return varchar2 as
      2    shval varchar2(100);
      3  begin
      4    select NVL(vname_suffix, vname_prefix) into shval from rdfownr.net1#rdf_value$ where value_id = val_id and rownum < 2;
      5    return substr(shval,1,20);
      6  exception
      7    when no_data_found then
      8      return '*' || val_id;
      9  end;
     10  /
    Function created.
    
    SQL> grant execute on shortval to public;
    Grant succeeded.
    
    SQL> create or replace view triples_view as
      2  select rdfownr.shortval(t.triple.rdf_s_id) subj, rdfownr.shortval(t.triple.rdf_p_id) pred, rdfownr.shortval(t.triple.rdf_c_id) obj, def_label
      3  from rdfownr.NET1#RDFT_PERSON t;
    View created.
     
    SQL> grant read on triples_view to public;
    Grant succeeded.
    
    SQL> create or replace view values_view as
      2  select value_id, value_name
      3  from rdfownr.net1#rdf_value$
      4  where (value_name NOT LIKE '%rdf%' and value_name NOT LIKE '%owl%' and canon_id is NULL);
    View created.
    
    SQL> grant read on values_view to public;
    Grant succeeded.
  4. RDFグラフに対してSQLのinsertを使用する際には、ファイングレイン・アクセス制御(FGAC)を設定します。

    ユーザーに割り当てられたラベルによって、ユーザーが挿入したデータに関連付けることができるラベルが決まります。これは、ユーザーに割り当てられたラベル、またはユーザーのラベルよりも優位性が下の任意のラベルになります。また、割り当てられたラベルによって、このような表のどのデータがユーザーに表示されるかが決まります。

    SQL> --
    SQL> -- INSERT using SQL Insert statement
    SQL> --
    SQL> 
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> 
    SQL> -- 1) use default label, which is 'SE::' or 1500 for rdfownr, for the triple as well as the values
    SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person',
      2  '<urn:john>','<urn:spouseOf>','<urn:mary>',
      3  'rdfownr','NET1'));
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> 
    SQL> -- check labels for the visible triples and values
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    john                   spouseOf               mary                   1500
    
    1 row selected.
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    urn:john                                                          1500
    urn:mary                                                          1500
    urn:spouseOf                                                      1500
    
    3 rows selected.
    
    SQL> 
    SQL> conn c/<password_for_c>
    Connected.
    SQL> -- 2) use default explicit label 'UN::' (1000) for the triple
    SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple, def_label) values (sdo_rdf_triple_s('person',
      2  '<urn:john>','<urn:secretId>','"jasmin#*!@"',
      3  sys.odcinumberlist(char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'TS::')),
      4  'rdfownr','NET1'), char_to_label('DEFENSE', 'UN::'));
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> 
    SQL> -- check labels for the visible triples and values
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    john                   secretId               jasmin#*!@             1000
    john                   spouseOf               mary                   1500
    
    2 rows selected.
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    jasmin#*!@                                                        3100
    urn:john                                                          1500
    urn:mary                                                          1500
    urn:secretId                                                      1000
    urn:spouseOf                                                      1500
    
    5 rows selected.
    
    SQL> 
    SQL> conn a/<password_for_a>1
    Connected.
    SQL> -- 3) use default label, which is 'UN::' or 1000 for user A, for both the triple as well as the values
    SQL> -- this triple already exists, but with a higher label (1500) and hence not visible to the current user: so, a duplicate triple gets inserted
    SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person',
      2  '<urn:john>','<urn:spouseOf>','<urn:mary>',
      3  'rdfownr','NET1'));
    
    1 row created.
    
    SQL> 
    SQL> -- 4) use default label ('UN::' or 1000) for the triple and all its values
    SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person',
      2  '<urn:childOf>','owl:inverseOf','<urn:parentOf>',
      3  'rdfownr','NET1'));
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> 
    SQL> -- check labels for the visible triples and values
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000
    
    3 rows selected.
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    urn:childOf                                                       1000
    urn:john                                                          1000
    urn:mary                                                          1000
    urn:parentOf                                                      1000
    urn:secretId                                                      1000
    urn:spouseOf                                                      1000
    
    6 rows selected.
    
    SQL> 
    SQL> conn b/<password_for_b>
    Connected.
    SQL> -- 5) use default label ('SE::' or 1500) for triple, but lowest label ('UN' or 1000) for values
    SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person',
      2  '<urn:spouseOf>','rdf:type','owl:SymmetricProperty',
      3  sys.odcinumberlist(char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'UN::')),
      4  'rdfownr','NET1'));
    
    1 row created.
    
    SQL> 
    SQL> -- check labels for the visible triples and values
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    4 rows selected..
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    urn:childOf                                                       1000
    urn:john                                                          1000, 1500
    urn:mary                                                          1000, 1500
    urn:parentOf                                                      1000
    urn:secretId                                                      1000
    urn:spouseOf                                                      1000, 1500
    
    6 rows selected.
    
    SQL> 
    SQL> conn c/<password_for_c>
    Connected.
    SQL> -- 6) use default label ('TS::' or 3100) for the triple
    SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person',
      2  '<urn:john>','<urn:childOf>','<urn:bob>',
      3  'rdfownr','NET1'));
    
    1 row created.
    
    SQL> COMMIT;
    
    Commit complete.
    
    SQL> 
    SQL> -- check labels for the visible triples and values
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   childOf                bob                    3100
    john                   secretId               jasmin#*!@             1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    5 rows selected.
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    jasmin#*!@                                                        3100
    urn:bob                                                           3100
    urn:childOf                                                       1000
    urn:john                                                          1000, 1500
    urn:mary                                                          1000, 1500
    urn:parentOf                                                      1000
    urn:secretId                                                      1000
    urn:spouseOf                                                      1000, 1500
    
    8 rows selected.
  5. 指定されたラベル・シーケンスに対して繰り返し反復処理を実行することにより、ラベルベースの推論を実行します。

    次のコードは、ラベル・シーケンス<1000, 1500, 3100>のラベルベースの推論を示しています。導出されたトリプルは、それなしでは導出できない最初期の(minimum)ラベルでマークされます。たとえば、導出されたトリプルbob parentOf johnには3100 ('TS::')というラベルが付きます。これは、ユーザーに少なくとも3100のラベルがある場合にのみjohn childOf bobが表示されるため、3100より下位のラベルでは導出できないからです。

    SQL> conn sys/<password_for_sys> as sysdba
    Connected.
    
    SQL> -- allow "exchange partition" operations used during inference
    SQL> grant EXEMPT ACCESS POLICY on schema rdfownr to rdfownr;
    Grant succeeded.
    
    SQL> conn c/<password_for_c>
    Connected.
    
    SQL> BEGIN
      2   sem_apis.create_inferred_graph('inf',
      3    sem_models('PERSON'),
      4    sem_rulebases('OWL2RL'),
      5    SEM_APIS.REACH_CLOSURE,
      6    null,
      7    null,
      8    ols_ladder_inf_lbl_seq=>'1000 1500 3100',
      9    network_owner=>'RDFOWNR',
     10    network_name=>'NET1'
     11  );
     12  END;
     13  /
    
    PL/SQL procedure successfully completed.
    
    SQL> conn sys/<password_for_sys> as sysdba
    Connected.
    
    SQL> -- "exchange partition" operations not needed any more
    SQL> revoke EXEMPT ACCESS POLICY on schema rdfownr from rdfownr;
    Revoke succeeded.
    
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    
    SQL> create or replace view inf_triples_view as
      2  select rdfownr.shortval(t.start_node_id) subj, rdfownr.shortval(t.p_value_id) pred, rdfownr.shortval(canon_end_node_id) obj, def_label
      3  from rdfownr.NET1#RDFI_INF t;
    View created.
    
    SQL> grant read on inf_triples_view to public;
    Grant succeeded.
    
    SQL> conn c/<password_for_c>
    Connected.
    
    SQL> -- check labels for the visible triples and values
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    bob                    parentOf               john                   3100
    mary                   spouseOf               john                   1500
    parentOf               inverseOf              childOf                1000
    spouseOf               inverseOf              spouseOf               1500
    
    4 rows selected.
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    1                                                                 3100
    jasmin#*!@                                                        3100
    true                                                              3100
    urn:bob                                                           3100
    urn:childOf                                                       1000
    urn:john                                                          1000, 1500
    urn:mary                                                          1000, 1500
    urn:parentOf                                                      1000
    urn:secretId                                                      1000
    urn:spouseOf                                                      1000, 1500
    
    10 rows selected
    
    SQL> 
    SQL> -- visibility note: users with lower label may sometimes be able to see a triple but not the higher-labeled values used in that triple
    SQL> conn a/<password_for_a>
    Connected.
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000
    
    3 rows selected.
    
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    parentOf               inverseOf              childOf                1000
    
    1 row selected.
    
    SQL> conn b/<password_for_b>
    Connected.
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    4 rows selected.
    
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    mary                   spouseOf               john                   1500
    parentOf               inverseOf              childOf                1000
    spouseOf               inverseOf              spouseOf               1500
    
    3 rows selected.
    
    SQL> conn c/<password_for_c>
    Connected.
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   childOf                bob                    3100
    john                   secretId               jasmin#*!@             1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    5 rows selected.
    
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    bob                    parentOf               john                   3100
    mary                   spouseOf               john                   1500
    parentOf               inverseOf              childOf                1000
    spouseOf               inverseOf              spouseOf               1500
    
    4 rows selected.
    
    SQL> conn q/<password_for_q>
    Connected.
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    4 rows selected.
    
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    mary                   spouseOf               john                   1500
    parentOf               inverseOf              childOf                1000
    spouseOf               inverseOf              spouseOf               1500
    
    3 rows selected.
    
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    4 rows selected.
    
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    mary                   spouseOf               john                   1500
    parentOf               inverseOf              childOf                1000
    spouseOf               inverseOf              spouseOf               1500
    
    3 rows selected.
  6. ラベル関数を定義して使用します。

    次のコードは、述語が<urn:salary>の場合に上位ラベル('SE::')をトリプルに関連付け、それ以外の場合は下位ラベル('UN::')を関連付けるラベル関数を、バルクロード時に使用する例を示しています。

    SQL> -- use of label functions and its use during bulk-load 
    SQL> conn sys/<password_for_sys>
    Connected.
    SQL> grant execute on to_lbac_data_label to rdfownr;
    
    Grant succeeded.
    
    SQL> 
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> 
    SQL> CREATE TABLE stage_table (
      2                       RDF$STC_sub varchar2(4000) not null,
      3                       RDF$STC_pred varchar2(4000) not null,
      4                       RDF$STC_obj varchar2(4000) not null
      5  );
    
    Table created.
    
    SQL> 
    SQL> insert into stage_table values ('<urn:john>','<urn:lastName>','"Smith"');
    
    1 row created.
    
    SQL> insert into stage_table values ('<urn:john>','<urn:salary>','"100K"');
    
    1 row created.
    
    SQL> commit;
    
    Commit complete.
    
    SQL> 
    SQL> -- define a label function for generating label for a given triple
    SQL> -- label function for generating labels for triples (in RDF_LINK$)
    SQL> CREATE OR REPLACE FUNCTION gen_triple_label_on_pid (p_value_id number) Return LBACSYS.LBAC_LABEL
      2  as
      3    i_label varchar2(80);
      4    vty varchar2(10);
      5    vnm varchar2(100);
      6  BEGIN
      7    select value_type, value_name into vty, vnm from rdfownr.net1#rdf_value$ where value_id=p_value_id;
      8    if (vty = 'UR' and vnm = 'urn:salary') then
      9      i_label := 'SE::';
     10    else
     11      i_label := 'UN::';
     12    end if;
     13    RETURN TO_LBAC_DATA_LABEL('DEFENSE',i_label);
     14  END;
     15  /
    
    Function created.
    
    SQL> 
    SQL> grant execute on gen_triple_label_on_pid to LBAC_TRIGGER;
    
    Grant succeeded.
    
    SQL> 
    SQL> -- ALTER_OLS_TABLE_POLICY to include use of label function for triples
    SQL> conn defense_admin/<password_for_defense_admin>
    Connected.
    SQL> exec sem_rdfsa.alter_ols_table_policy('triple', 'label_function', 'rdfownr.gen_triple_label_on_pid(:new.p_value_id)', network_owner=>'rdfownr',network_name=>'net1');
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from lbacsys.all_sa_table_policies where schema_name='RDFOWNR' order by policy_name, table_name;
    
    POLICY_NAM SCHEMA_NAME                                                                                                                      TABLE_NAME                     STATUS
    ---------- -------------------------------------------------------------------------------------------------------------------------------- ------------------------------ --------
    TABLE_OPTIONS
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    FUNCTION
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    PREDICATE
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    DEFENSE    RDFOWNR                                                                                                                          NET1#RDF_LINK$                 ENABLED
    READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL, LABEL_DEFAULT, LABEL_UPDATE, CHECK_CONTROL
    rdfownr.gen_triple_label_on_pid(:new.p_value_id)
    
    DEFENSE    RDFOWNR                                                                                                                          NET1#RDF_VALUE$                ENABLED
    READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL, LABEL_DEFAULT, LABEL_UPDATE, CHECK_CONTROL
    
    2 rows selected.
    
    SQL> 
    SQL> -- bulk-load uses designated label function to mark the salary triple as 'SE::' (1500) while marking the "lastName" triples as 'UN::' (1000)
    SQL> conn rdfownr/<password_for_rdfownr>
    Connected.
    SQL> exec sem_apis.bulk_load_from_staging_table('person','rdfownr','stage_table',network_owner=>'rdfownr',network_name=>'net1');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3;
    
    SUBJ                   PRED                   OBJ                    LABELS
    ---------------------- ---------------------- ---------------------- ------------------------------
    childOf                inverseOf              parentOf               1000
    john                   lastName               Smith                  1000
    john                   salary                 100K                   1500
    john                   secretId               *7305832552150903811   1000
    john                   spouseOf               mary                   1000, 1500
    spouseOf               type                   SymmetricProperty      1500
    
    6 rows selected.
    
    SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1;
    
    VALUE_NAME                                                        LABELS
    ----------------------------------------------------------------- ------------------------------
    100K                                                              1500
    Smith                                                             1500
    urn:childOf                                                       1000
    urn:john                                                          1000, 1500
    urn:lastName                                                      1500
    urn:mary                                                          1000, 1500
    urn:parentOf                                                      1000
    urn:salary                                                        1500
    urn:secretId                                                      1000
    urn:spouseOf                                                      1000, 1500
    
    10 rows selected