Warning:
This wiki has been archived and is now read-only.

Direct Mapping in RIF

From RDB2RDF
Jump to: navigation, search

Direct Mapping

This section show the direct mapping rules to expose a relational database as OWL, RDF-S and RDF; object and datatype properties for Direct Graph Many to Many mapping and a SQL recipe for generating a direct graph.

Direct Mapping Relational Database to OWL/RDF-S

A simplified version of the Direct Mapping rules from Relational Database to OWL/RDF-S are presented. The following rules direct map to OWL (using owl:ObjectProperty and owl:DatatypeProperty). These rules can be simplified in order to direct map only to RDF-S (use rdf:Property instead of owl:ObjectProperty and owl:DatatypeProperty)

Note: there might be some mistakes

Example Relational Database

Employee(emp_id, emp_name, emp_deptId)
Department(dept_id, dept_name, dept_function)

Note: a relation can also be a user generated SQL query or a View ( a la SQL-based approach)

Predicates

Rel(r) = r is a relation; e.g. Rel(Employee) holds, Rel(emp_id) does not
Attr(x,r) = x is an attribute in relation r; e.g. Attr(emp_id,Employee) holds
PK(x,r) = x is the (single or composite) primary key of relation r; e.g. PK({emp_id},Employee) holds
FK(x,r,y,s) = x is a (single or composite) foreign key in relation r and references y in relation s; e.g. FK({emp_deptId},Employee,{dept_id},Department) holds 
NonFK(x,r) = x is an attribute in relation r that does not participate in any foreign key; e.g. NonFK(emp_name,Employee) holds

Functions

type(x) = maps an attribute x to its suitable OWL recommended data type

Rules

Document(
 Prefix(pred http://www.w3.org/2007/rif-builtin-predicate#)
 Prefix(func http://www.w3.org/2007/rif-builtin-function#)
 Prefix(ex   http://example.org/example#)
 Group
 (
   Forall ?r ?s ?t (
   ex:bin_rel(?r ?s ?t) :-
     ex:rel(?r)
     ex:fk(?q ?r ?x ?t)
     ex:fk(?p ?r ?y ?s)
     pred:literal-not-identical(?p ?q)
   )
   
   Forall ?r (
   ex:class(?r) :-
     ex:rel(?r)
     Not (ex:bin_rel(?r))
   )
   
   Forall ?r ?s ?t(
   object_p(?r ?s ?t) :-
     ex:bin_rel(?r ?s ?t)
     ex:rel(?s)
     ex:rel(?t)
     Not(ex:bin_rel(?s ?a ?b)
     Not(ex:bin_rel(?t ?c ?d)
   )
   
   Forall ?x ?s ?y ?t(
   object_p(?x ?s ?t) :-
     ex:fk(?x ?s ?y ?t)
     ex:rel(?s)
     ex:rel(?t)
     Not(bin_rel(?s ?a ?b)
     Not(bin_rel(?t ?c ?d)
   )
   
   Forall ?x ?r(
   datatype_p(?x ?r ex:type(?x)) :-
     NonFk(?x ?r)
   )
 )
)

Rules EGP @@another crack at the rules, longer, but with expository variable names - ericP

Document(
 Prefix(pred http://www.w3.org/2007/rif-builtin-predicate#)
 Prefix(func http://www.w3.org/2007/rif-builtin-function#)
 Prefix(ex   http://example.org/example#)
 Group
 (
   # bin_rel: Binary many-to-many relations from one relation to another
   # e.g. bin_rel(db:TaskAssignments, db:Employee, db:Task)
   #   && bin_rel(db:TaskAssignments, db:Task, db:Employee)
   Forall ?m2mRel ?fromRel ?toRel (
   ex:bin_rel(?m2mRel ?fromRel ?toRel) :-
     ex:rel(?m2mRel)
     ex:fk(?fromFK ?m2mRel ?fromPK ?fromRel)
     ex:fk(?toFK ?m2mRel ?toPK ?toRel)
     pred:literal-not-identical(?fromFK ?toFK)
   )
   
   # class: Relations which are not binary many-to-many relations imply a class.
   # e.g. class(Employee)
   Forall ?r (
   ex:class(?r) :-
     ex:rel(?r)
     Not (ex:bin_rel(?r))
   )
   
   # object_p: Binary many to many relations in which neither foreign key is to another bin_rel imply an object property.
   # e.g. object_p(TaskAssignment, db:Employee, db:Task)
   #   && object_p(TaskAssignment, db:Task, db:Employee)
   Forall ?m2mRel ?fromRel ?toRel (
   object_p(?m2mRel ?fromRel ?toRel) :-
     ex:bin_rel(?m2mRel ?fromRel ?toRel)
     ex:rel(?fromRel)
     ex:rel(?toRel)
     Not(ex:bin_rel(?fromRel ?a ?b)
     Not(ex:bin_rel(?toRel ?c ?d)
   )
   
   # object_p: For relations which are not binary, many-to-many, foreign keys which reference non-bin_rels imply an object propery.
   # e.g. object_p(emp_deptId, Employee, Department) @@ inconsistent with above object_p, what's the type signature?
   Forall ?fromFK ?fromRel ?toPK ?toRel(
   object_p(?fromFK ?fromRel ?toRel) :-
     ex:fk(?fromFK ?fromRel ?toPK ?toRel)
     ex:rel(?fromRel) # aren't the 2nd and 4th args of fk() constrained to be Relations?
     ex:rel(?toRel)
     Not(bin_rel(?fromRel ?a ?b)
     Not(bin_rel(?toRel ?c ?d)
   )
   
   # datatype_p: Non-foreign key attributes in @any@ relation imply a datatype property.
   Forall ?attr ?rel(
   datatype_p(?attr ?rel ex:type(?attr)) :-
     NonFk(?attr ?rel)
   )
 )
)


Following our running example we would identify the following OWL elements

Class(Employee)
Class(Department)
Object_p(emp_deptId, Employee, Department)
Datatype_p(emp_name, Employee, string)
Datatype_p(dept_name, Department, string)

Direct Mapping Relational Database to RDF

Based on the previous direct mapping rules, we have identified what elements of the Relational Database are mapped to classes or properties.

The following is an algorithm to produce the RDF triples based on the identified classes and properties:

if(x is a Class)
  SELECT "x"+PK_of_x as s, "rdf:type" as p, "x" as o FROM x
if(x is a Datatype Property)
 SELECT "x.domain"+PK_of_Domain as s, "x" as p, x.range+"^^x.type" as o from x.domain
if(x is a Object Property)
 SELECT "x.domain"+PK_of_Domain as s, "x" as p, "x.range"+PK_of_Domain as o FROM x.domain

The following example demonstrates how the RDF triples can be produced based on our running example:

SELECT concat("Employee",emp_id) as s, "rdf:type" as p, "Employee" as o FROM Employee
SELECT concat("Employee",emp_id) as s, "emp_name" as p, concat(emp_name, "^^xsd:string") as o FROM Employee
SELECT concat("Employee",emp_id) as s, "emp_dept" as p, concat("Department", emp_deptId) as o FROM Employee

These SELECT statements are equivalente to the following Datalog rules (apologies for mixing RIF and Datalog. This needs to be written in RIF)

triple(concat("Employee",emp_id), rdf:type, "Employee") :- Employee(emp_id, _, _, ...)
triple(concat("Employee",emp_id), "emp_name", concat(emp_name,"^^xsd:string") :- Employee(emp_id, emp_name, _, ...)
triple(concat("Employee",emp_id), "emp_dept", concat("Department", emp_deptId) :- Employee(emp_id, _, _, ..., emp_deptId)

Please note that we are not considering how the URIs are generated