Graffiti - relational RDF store for Ruby

Synopsis

require 'sequel'
require 'yaml'
require 'graffiti'

db = Sequel.connect(:adapter => 'pg', :database = > dbname)
config = File.open('rdf.yaml') {|f| YAML.load(f.read) }
store = Graffiti::Store.new(db, config)

data = store.fetch(%{
  SELECT ?date, ?title
  WHERE (dc::date ?r ?date FILTER ?date >= :start)
        (dc::title ?r ?title)
  ORDER BY ?date DESC}, 10, 0, :start => Time.now - 24*3600)

puts data.first[:title]

Description

Graffiti is an RDF store based on dynamic translation of RDF queries into SQL. Graffiti allows to map any relational database schema into RDF semantics and vice versa, to store any RDF data in a relational database.

Requirements

Graffiti uses Sequel to connect to database backend and provides a DBI-like interface to run RDF queries in Squish query language from Ruby applications. SynCache object cache is used for in-process cache of translated Squish queries.

Query Language

Graffiti implements Squish RDF query language with several extensions. A query may include following clauses:

  • SELECT: comma-separated list of result expressions, which may be variables or aggregate functions.

  • WHERE: main graph pattern, described as a list of triple patterns. Each triple is enclosed in parenthesis and includes predicate, subject and object. Predicate must be a URL and may use a shorthand notation with namespace id separated by double colon. Subject may be a URL, internal resource id, or variable. Object may be a URL, internal resource id, variable, or literal. Values of variables bound by the triple pattern may be bound by an optional FILTER expression.

  • EXCEPT: negative graph pattern. Solutions that match any part of the negative graph pattern are excluded from the result set.

  • OPTIONAL: optional graph pattern. Variables defined in the optional pattern are only included in the result set only for solutions that match corresponding parts of the optional graph pattern.

  • LITERAL: global filter expression. Used for expressions that involve variables from different triple patterns.

  • GROUP BY: result set aggregation criteria.

  • ORDER BY: result set ordering criteria.

  • USING: namespaces definitions. Namespaces defined in the RDF store configuration do not have to be repeated here.

A basic update language is also implemented. A Squish assert statement uses the same structure as a query, with SELECT clause replaced by either one or both of the following clauses:

  • INSERT: list of variables representing new resources to be inserted into the RDF graph.

  • UPDATE: list of assignments of literal expressions to variables bound by a solution.

Assert statement will only update one solution per invocation, if more solutions match the graph pattern, only the first will be updated.

Relational Data

Relational data has to be adapted for RDF access using Graffiti. The adaptation is non-intrusive and will not break compatibility with existing SQL queries.

Following schema changes are required for all cases:

  • Create rdfs:Resource superclass table with auto-generated primary key.

  • Replace primary keys of mapped subclass tables with foreign keys referencing the rdfs:Resource table (existing foreign keys may need to be updated to reflect this change.

  • Register rdfs:subClassOf inference database triggers to update the rdfs:Re-source table and maintain foreign keys integrity on all changes in mapped subclass tables.

Following changes may be necessary to support optional RDF mapping features:

  • Register database triggers for other cases of rdfs:subClassOf entailment.

  • Create triples table (required to represent non-relational RDF data and RDF statement reification).

  • Add sub-property qualifier attributes referencing property URIref entry in the rdfs:Resource table for each attribute mapped to a super-property.

  • Create transitive closure tables, register owl:TransitiveProperty inference triggers.

Example of RDF map and corresponding triggers can be found in doc/examples/.

Copying

Copyright (c) 2002-2011  Dmitry Borodaenko <[email protected]>

This program is free software.
You can distribute/modify this program under the terms of the GNU
General Public License version 3 or later.