7.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.

7.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.

7.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;

7.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), matchOpt varchar2(4000), updOpt varchar2(4000));
      Table created.
    2. Define the SPARQL rules using INSERT statements.
      SQL> INSERT INTO sparql_tab VALUES ('PREFIX my1: <http://my.org/>
        2      INSERT {  ?s ?p my1:x  }
        3      WHERE  {  ?s ?p ?o  }', 'FINAL_VALUE_NL', 'PARALLEL(2) dynamic_sampling(6)');
      1 row created.
      SQL> INSERT INTO sparql_tab VALUES ('PREFIX my1: <http://my.org/>
        2      INSERT {  ?s ?p my1:y  }
        3      WHERE  {  ?s ?p ?o  }', NULL, 'PARALLEL(2) dynamic_sampling(6)');
      1 row created.
      SQL> INSERT INTO sparql_tab VALUES ('PREFIX my1: <http://my.org/>
        2      INSERT {  ?s ?p my1:z  }
        3      WHERE  {  ?s ?p ?o }', 'FINAL_VALUE_NL', NULL);
      1 row created.
      SQL> COMMIT;
      Commit complete

      See also Storing SPARQL Rules for more information.

    3. Optionally, verify the defined rules by querying the table:
      RULE                                               MATCHOPT             UPDOPT
      -------------------------------------------------- -------------------- --------------------------------------------------
      PREFIX my1: <http://my.org/>                       FINAL_VALUE_NL       PARALLEL(2) dynamic_sampling(6)
          INSERT {  ?s ?p my1:x  }
          WHERE  {  ?s ?p ?o  }
      
      PREFIX my1: <http://my.org/>                                            PARALLEL(2) dynamic_sampling(6)
         INSERT {  ?s ?p my1:y  }
         WHERE  {  ?s ?p ?o  }
      
      PREFIX my1: <http://my.org/>                       FINAL_VALUE_NL
         INSERT {  ?s ?p my1:z  }
         WHERE  {  ?s ?p ?o }
      
  2. Create a SPARQL inferred graph by calling the SEM_APIS.CREATE_SPARQL_INFERRED_GRAPH procedure.
    SQL> EXEC SEM_APIS.CREATE_SPARQL_INFERRED_GRAPH('SI1', sem_models('M1'),'RDFUSER','sparql_tab','Rule', 'matchOpt', 'updOpt', 3, network_owner=>'RDFUSER', network_name=>'NET1');
    PL/SQL procedure successfully completed.
    
    SQL> SELECT * FROM RDFUSER.NET1#SEM_RULES_INDEX_INFO where index_name='SI1';
    
    OWNER
    --------------------------------------------------------------------------------
    INDEX_NAME
    --------------------------------------------------------------------------------
    INDEX_VIEW_NAME
    --------------------------------------------------------------------------------
    STATUS
    --------------------------------------------------------------------------------
    MODEL_COUNT RULEBASE_COUNT
    ----------- --------------
    RDFUSER
    SI1
    NET1#RDFI_SI1
    VALID
    	  1		 0
  3. Query the SPARQL inferred graph just like querying any other standard inferred graphs.
    For instance, the following example creates an RDF graph collection directly targeting triples in the SPARQL inferred graph.
    SQL> EXEC SEM_APIS.CREATE_RDF_GRAPH_COLLECTION('VM100',inferred_graphs=>SEM_Entailments('SI1'),network_owner=>'RDFUSER',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.

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

    SQL> SELECT s, p, o FROM TABLE(
      2  SEM_MATCH('
      3  SELECT * WHERE {
      4     ?s ?p ?o  }
      5  ', sem_models('VM100'),null,null,null,null,'',network_owner=>'RDFUSER',network_name=>'NET1'))
      6  ORDER BY 1,2,3;
    
    
    S                    P                    O
    -------------------- -------------------- --------------------
    Bill                 knows                http://my.org/x
    Bill                 knows                http://my.org/y
    Bill                 knows                http://my.org/z
    Bill                 mbox                 http://my.org/x
    Bill                 mbox                 http://my.org/y
    Bill                 mbox                 http://my.org/z
    Bill                 works_for            http://my.org/x
    Bill                 works_for            http://my.org/y
    Bill                 works_for            http://my.org/z
    Fred                 mbox                 http://my.org/x
    Fred                 mbox                 http://my.org/y
    Fred                 mbox                 http://my.org/z
    Fred                 works_for            http://my.org/x
    Fred                 works_for            http://my.org/y
    Fred                 works_for            http://my.org/z
    John                 knows                http://my.org/x
    John                 knows                http://my.org/y
    John                 knows                http://my.org/z
    John                 mbox                 http://my.org/x
    John                 mbox                 http://my.org/y
    John                 mbox                 http://my.org/z
    John                 works_for            http://my.org/x
    John                 works_for            http://my.org/y
    John                 works_for            http://my.org/z
    Matt                 knows                http://my.org/x
    Matt                 knows                http://my.org/y
    Matt                 knows                http://my.org/z
    Matt                 mbox                 http://my.org/x
    Matt                 mbox                 http://my.org/y
    Matt                 mbox                 http://my.org/z
    Matt                 works_for            http://my.org/x
    Matt                 works_for            http://my.org/y
    Matt                 works_for            http://my.org/z
    
    33 rows selected.
  4. Optionally, drop the SPARQL inferred graph by calling SEM_APIS.DROP_INFERRED_GRAPH.
    SQL> EXEC SEM_APIS.DROP_INFERRED_GRAPH('SI1', network_owner=>'RDFUSER',network_name=>'NET1');
    
    PL/SQL procedure successfully completed.