The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

TripleStore - An SQL-Free Triple Store API with a Perl Query Language.

SYNOPSIS

  use TripleStore;
  use TripleStore::Driver::MySQL;
  
  my $::DB = new TripleStore (
      new TripleStore::Driver::MySQL (
          "DBI:mysql:database=test",
          "root",
          "someSecretPassword",
      )
  );
  
  $::DB->tx_start();
  eval { do_some_stuff() };
  $@ ? $::DB->tx_abort() ? $::DB->tx_stop();

  $::DB = undef;

SUMMARY

TripleStore is a Perl interface for a triple store. Currently a quite naive MySQL implementation is provided. Alternative SQL implementations can be developed by subclassing TripleStore::Driver or any of its subclasses (such as TripleStore::Driver::SQL).

Note that TripleStore API strives to NOT be connected in any way with SQL (especially for querying). There might be a few common points, but as you will see TripleStore is quite neutral at that level.

BASIC OPERATIONS / HOW IT WORKS

Constructing a triple store object.

To construct a triple store object, you need to instanciate a driver first. Currently there's only one driver available, so that's not so hard :=)

  sub gimme_driver
  {
      new TripleStore::Driver::MySQL (
          "DBI:mysql:database=test",
          "root",
          "someSecretPassword",
      );
  }

Then you need to instanciate a TripleStore object and put it somewhere where you can access it everywhere in your program.

  sub main
  {
      local $::DB = new TripleStore (gimme_driver());
      $::DB->tx_start(); # starts a transaction
      eval {
          # here we're gonna do
          # plenty of stuff
          # that involves the triple store.
      }
      $@ ? $::DB->tx_abort() : $::DB->tx_stop();
  }

Inserting new triples

  $::DB->insert ($subject, $predicate, $object);

Deleting existing triples

In order to delete triples you need to define some condition. You do that using a clause object.

  # clause that matches all triples with:
  #    predicate eq 'price'
  #    object    >  100.25
  my $clause = $::DB->clause (undef, 'price', [ '>', 125.25 ]);
  $::DB->delete ($clause);

The current MySQL driver does not support complex conditions for deletion yet (i.e. $clause1 & ( $clause2 | $clause3 )).

Updating exising triples

Same as delete, except that you define a hashref of elements to set, i.e.

  # this is a silly update:
  # for everything that has a price greater than
  # 125.25, set the price to 90.
  my $clause = $::DB->clause (undef, 'price', [ '>', 125.25 ]);
  $::DB->update ( { object => 90 }, $clause);

You can update on 'subject', 'predicate' or 'object'.

QUERYING THE TRIPLE STORE

StoreTriple features a quite nice query interface which is inspired from the rdfdb-style queries.

In rdbf, queries are expected to be parsed from a form such as:

  select ( ?x ?y ) from triple where (?x worksFor ?y) (?y name 'BBC')

With TripleStore, this translates as:

  my $x = $::DB->var();
  my $y = $::DB->var();
  my $rs = $::DB->select ($x, $y,
      $::DB->clause ($x, 'worksFor', $y) &
      $::DB->clause ($y, 'name', 'BBC')
  );

Except that TripleStore lets you do a bit more...

Making complex queries

  my $complex = $clause1 & ( $clause2 | $clause3 | ( $clause4 & $clause5 ) );

Sorting variables

  # same query, sorted by alphabetical order on $x
  # and then by descending numerical order on $y
  my $rs = $::DB->select ($x, $y,
      $::DB->clause ($x, 'worksFor', $y) &
      $::DB->clause ($y, 'name', 'BBC')
      $::DB->sort_str_asc ($x), $::DB->sort_num_desc ($y)
  );

The available sorting functions are:

  $::DB->sort_str_asc  ($variable);
  $::DB->sort_str_desc ($variable);
  $::DB->sort_num_asc  ($variable);
  $::DB->sort_num_desc ($variable);

Limiting

  # same query, but limited to the 10 first rows
  my $rs = $::DB->select ($x, $y,
      $::DB->clause ($x, 'worksFor', $y) &
      $::DB->clause ($y, 'name', 'BBC')
      $::DB->limit (0, 10) # offset, rows
  );

  # same as above, but with a different approach
  my $rs = $::DB->select ($x, $y,
      $::DB->clause ($x, 'worksFor', $y) &
      $::DB->clause ($y, 'name', 'BBC')
      $::DB->limit_page (1, 10) # first page, 10 rows per page
  );

Selecting on...

Strings:

  $::DB->clause ($y, 'name', 'BBC') # equality
  $::DB->clause ($y, 'name', [ 'ne', 'BBC' ]) # non equality
  $::DB->clause ($y, 'name', [ 'lt', 'BBC' ]) # lesser than
  $::DB->clause ($y, 'name', [ 'le', 'BBC' ]) # lesser or equals
  $::DB->clause ($y, 'name', [ 'gt', 'BBC' ]) # greater than
  $::DB->clause ($y, 'name', [ 'ge', 'BBC' ]) # greater or equals
  $::DB->clause ($y, 'name', [ 'like', '%BBC%' ]) # like
  $::DB->clause ($y, 'name', [ 'unlike', '%BBC%' ]) # unlike

Numeric:

  $::DB->clause ($y, 'someNumericValue', [ '==', 12 ] ) # equality
  $::DB->clause ($y, 'name', [ '!=', 12 ] ) # non equality
  $::DB->clause ($y, 'name', [ '<', 12 ] )  # lesser than
  $::DB->clause ($y, 'name', [ '<=', 12 ] ) # lesser or equals
  $::DB->clause ($y, 'name', [ '>', 12 ] )  # greater than
  $::DB->clause ($y, 'name', [ '>=', 12 ] ) # greater or equals

Looping through the results.

When you invoke the select() method, a ResultSet object is returned. You can use that ResultSet object to loop through the results.

  my $rs = $::DB->select ($x, $y,
      $::DB->clause ($x, 'worksFor', $y) &
      $::DB->clause ($y, 'name', 'BBC')
      $::DB->limit_page (1, 10) # first page, 10 rows per page
  );

  while (my $arrayref = $rs->next())
  {
      my $x_variable = $arrayref->[0];
      my $y_variable = $arrayref->[1];
  }

KNOWN BUGS

This is an ALPHA release. There is no known bugs, which means that there's plenty of them to find out... reports and patches appreciated!

AUTHOR

Copyright 2002 - Jean-Michel Hiver <jhiver@mkdoc.com>

This module free software and is distributed under the same license as Perl itself.

SEE ALSO

  # The TripleStore mailing list
  http://www.email-lists.org/mailman/listinfo/triplestore
  
  # Triple Querying with SQL
  http://www.picdiary.com/triplequerying/