9.3 SPARQL Rule-Based Inference

The RDF Graph inference extension architecture enables you to add SPARQL rule-based inference.

You can avail the full power of the SPARQL query language by specifying matching conditions for inferring new RDF triples. Unlike the limitations of normal inference, the inferred triples created using this process may even contain new RDF terms that were not originally present in the RDF network prior to the start of the inference task.

You can define your own rules using SPARQL update INSERT statements.

9.3.1 Storing SPARQL Rules

You can store any number of your own rules in any column of VARCHAR or CLOB type in your own tables along with match options and update options. The match options and update options are the same as match_options and options, respectively, used in SEM_APIS.UPDATE_RDF_GRAPH. They are used for hints that optimize SPARQL update operations and can be NULL.

All these rules are applied to an RDF triple store during inference by the SEM_APIS.CREATE_SPARQL_INFERRED_GRAPH API.

User rules can be represented as INSERT WHERE (or INSERT DATA) statements. For example:

PREFIX ex: <http://my.org/>
INSERT { ?x a ex:Employee }
WHERE  { ?x ex:hours ?hrs FILTER (?hrs >= 40) }

Due to the nature of arbitrary rules, it cannot be guaranteed that the inference will reach the transitive closure. Hence, the maximum number of iterations should be specified. In addition, user rules can violate open world assumption which RDF inference is based on. The use of SPARQL features that depend on a closed world assumption (that is, NOT EXISTS) may lead to inconsistent inferred graph results. As such, their use should be avoided if possible.

9.3.2 Setting Up Sample Data to Create a SPARQL Inferred Graph

To run the example described in Example Workflow to Create and Query a SPARQL Inferred Graph, you must prepare the database as described in the following steps:
  1. Connect to Oracle AI Database as a SYSTEM user with a DBA privilege (or as ADMIN user on Autonomous AI Database Serverless).
    CONNECT system/<password-for-system-user>
  2. Create a database user to create and own the RDF network.
    create user RDFUSER identified by <password_for_rdfuser>;
  3. Grant the necessary privileges to the new database user.
    GRANT CONNECT, RESOURCE, CREATE VIEW, UNLIMITED TABLESPACE TO rdfuser;
  4. Connect to the database as rdfuser.
    CONNECT rdfuser/<password-for-rdf-user>;
  5. Create a schema-private RDF network named NET1.
    EXEC SEM_APIS.CREATE_RDF_NETWORK(tablespace_name =>'tbs_3', network_owner=>'RDFUSER', network_name=>'NET1');
  6. Create an RDF graph m1 in RDF network NET1.
    EXEC SEM_APIS.CREATE_RDF_GRAPH('m1', null, null, network_owner=>'RDFUSER',network_name=>'NET1');
  7. Insert the RDF triples into the RDF graph .
    BEGIN
      SEM_APIS.UPDATE_RDF_GRAPH('m1',
      'PREFIX ex: <http://my.org/>
    	INSERT DATA {
    	  ex:adam ex:hours 20 .
    	  ex:bill ex:hours 25 .
    	  ex:carl ex:hours 30 .
    	  ex:drew ex:hours 35 .
    	  ex:eric ex:hours 40 .
    	}',
      network_owner=>'rdfuser', network_name=>'net1');
    END;
    /
    COMMIT;

9.3.3 Example Workflow to Create and Query a SPARQL Inferred Graph

The example describes the steps for storing SPARQL rules, creating a SPARQL inferred graph by applying the stored rules, querying the graph, and finally dropping the inferred graph.
Before you begin, set up the sample data as described in Setting Up Sample Data to Create a SPARQL Inferred Graph.
  1. Store the SPARQL rules as shown in the following steps:
    1. Create a table to store the SPARQL rules.
      SQL> CREATE TABLE sparql_tab(rule varchar2(4000));
      Table created.
    2. Define the SPARQL rules using INSERT statements.
      SQL> INSERT INTO sparql_tab values ('PREFIX ex: <http://my.org/>
        2  	 INSERT {  ?x a ex:Employee  }
        3  	 WHERE	{  ?x ex:hours ?hrs FILTER (?hrs >= 40)  }');
      
      1 row created.
      
      SQL> INSERT INTO sparql_tab values ('PREFIX ex: <http://my.org/>
        2  	 INSERT {  ?x a ex:Consultant  }
        3  	 WHERE	{  ?x ex:hours ?hrs FILTER (?hrs <= 20)  }');
      
      1 row created.
      
      SQL> INSERT INTO sparql_tab values ('PREFIX ex: <http://my.org/>
        2  	 INSERT {  ?x a ex:PartTimer  }
        3  	 WHERE	{  ?x ex:hours ?hrs FILTER (?hrs > 20 && ?hrs < 40)  }');
      
      1 row created.
      
      SQL> INSERT INTO sparql_tab values ('PREFIX ex: <http://my.org/>
        2  	 INSERT {  ?x ex:similarPartTimerAs ?y	}
        3  	 WHERE	{  ?x a ex:PartTimer ; ex:hours ?xhrs .
        4  		   ?y a ex:PartTimer ; ex:hours ?yhrs .
        5  		   FILTER ( (?x != ?y) && (ABS(?xhrs - ?yhrs) <= 5))  }');
      
      1 row created.
      
      SQL> COMMIT;
      Commit complete

      See also Storing SPARQL Rules for more information.

  2. Create a SPARQL inferred graph X1 by calling the SEM_APIS.CREATE_SPARQL_INFERRED_GRAPH procedure.
    SQL> EXEC SEM_APIS.CREATE_SPARQL_INFERRED_GRAPH('X1',sem_models('M1'),'rdfuser','sparql_tab','Rule', null, null, 3, network_owner=>'rdfuser',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.
  3. Query the SPARQL inferred graph just like querying any other standard inferred graphs.
    For instance, the following example creates an RDF graph collection with only the inferred triples.
    SQL> EXEC SEM_APIS.CREATE_RDF_GRAPH_COLLECTION('VM_X1_ONLY',inferred_graphs=>SEM_Entailments('X1'),network_owner=>'rdfuser',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.

    You can use a SEM_MATCH query to verify the contents of the inferred graph.

    SQL> SELECT s$rdfterm, p$rdfterm, o$rdfterm FROM TABLE(
      2  SEM_MATCH('
      3  SELECT * WHERE {
      4  	?s ?p ?o  }
      5  ', sem_models('VM_X1_ONLY'),null,null,null,null,' PLUS_RDFT=VC ',network_owner=>'rdfuser',network_name=>'NET1'))
      6  ORDER BY 1,2,3;

    The following shows the output of the preceding SEM_MATCH query.

    S$RDFTERM                      P$RDFTERM                                          O$RDFTERM                                                                     
    ------------------------------ -------------------------------------------------- ------------------------------                                                
    <http://my.org/adam>           <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://my.org/Consultant>                                                    
    <http://my.org/bill>           <http://my.org/similarPartTimerAs>                 <http://my.org/carl>                                                          
    <http://my.org/bill>           <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://my.org/PartTimer>                                                     
    <http://my.org/carl>           <http://my.org/similarPartTimerAs>                 <http://my.org/bill>                                                          
    <http://my.org/carl>           <http://my.org/similarPartTimerAs>                 <http://my.org/drew>                                                          
    <http://my.org/carl>           <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://my.org/PartTimer>                                                     
    <http://my.org/drew>           <http://my.org/similarPartTimerAs>                 <http://my.org/carl>                                                          
    <http://my.org/drew>           <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://my.org/PartTimer>                                                     
    <http://my.org/eric>           <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://my.org/Employee>                                                      
    
    9 rows selected.
  4. Optionally, drop the SPARQL inferred graph by calling SEM_APIS.DROP_INFERRED_GRAPH.
    SQL> EXEC SEM_APIS.DROP_INFERRED_GRAPH('X1', network_owner=>'RDFUSER',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.