SWI-Prolog Jasmine (ODB) Interface
Jan Wielemaker
SWI,
University of Amsterdam
The Netherlands
E-mail: jan@swi.psy.uva.nl
The Jasmine interface provides a client interface to the Object Oriented Jasmine database. The interface consists of two layers. The first is a simple wrapper around the Jasmine C-interface. The second provides utility predicates providing more high-level access to Jasmine. |
Jasmine is an object-oriented database (ODB), implementing ODQL (Object Database Query Language). It provides a C-interface based on the following components:
Below is the definition of the basic ODB access predicates defined in
jasmine.c
.
Sessions are accessed using a session-handle. This opaque handle is normally preserved in the Prolog database.
[vnode::]/jasmine/jasmine
ODQL statement are passed in textual form and specified either as atoms or SWI-Prolog strings. The latter makes it possible to construct statements using sformat/3. See also odb_exec_odql/3.
Variables play a vital role in the interface. Interface variables are defined using ODQL statements. They are scoped to the session, but otherwise global. There are two approaches to deal with this. One is to define a suitable set of variables for the application at startup and the other is to create them as they are needed. In the latter case one should be sure the variable name is currently not in use. In some of the examples we therefore see:
undefVar pcount; Integer pcount; |
From this example we learn that variables are typed. The type is accessible through the C-interface and used by the access predicate to perform suitable conversion to Prolog.
The representation of Value depends on the type of Name in the database interface.
true
or
false
.
decimal(Digits, Precision, Scale)
. See the Jasmine C-API
docs for details.
Nil
[])). (1)
ByteSequences
, represented as Prolog
atoms.
tuple(...Arg...)
, where Arg is the
converted value for the corresponding position in the tuple.
This translation currently does not deal with the type-ambiguities. It is currently not possible to set nil-variables to a boolean, byte-sequence or date. This problem can be fixed by using an ODQL query to fill the empty variable with an object of the requested type.
Database queries normally yield collections as results. The interface simply converts collections into Prolog lists. The current interface does not yet provide mechanisms for fetching part of a collection. Note that, using ODQL statements it is possible to get the length of a collection before conversion:
collection_length(SH, Collection, Length) :- odb_exec_odql(SH, 'Integer len;'), odb_exec_odql(SH, 'len = ~w.count();', [Collection]), odb_get_var(SH, len, Length). |
The predicates of the previous section provide all important aspects of the C-API to the Prolog user. The provided access however is very low-level. A very first start has been made to provide a number of utility predicates.
{Goal}
is the same as {}(Goal)
.
Here is an example, extracting the available class-families from the Jasmine database:
families(SH, List) :- odql(SH, [ ss:'Bag<String>' ], [ 'ss = FamilyManager.getAllFamilies();', get_list(ss, List) ]). |
All errors are reported using Prolog exceptions. This package raises
two types of exceptions. If Prolog arguments cannot be converted into
the desired data, normal Prolog type_error
and
instantiation_error
exceptions are raised. Jasmine calls
returning an error are translated into an error term of the format
error(package(jasmine, ErrorId)
, Context)
Where Context is
context(Message, _)
In this term, ErrorId is the (numerical) error identifier raised by Jasmine and Message is Jasmine's textual representation of the error.
The interface defined here provides the foreign-language basis for a more advanced Prolog ODQL interface. Specifying all ODQL as strings and dealing with the interface variables is not a desirable way to deal with ODQL. A more fundamental approach is to define a Prolog API for ODQL and an interface for translating these Prolog queries into textual ODQL calls. For example, the families/2 example above could be written as:
families(SH, Families) :- odql(Families:bag(string) = 'FamilyManager'.getAllFamilies). |
The jasmine package has currently been build only on Windows. As Jasmine is also available on Unix, the standard SWI-Prolog package infra-structure for Unix foreign packages is provided.
Installation on Unix system uses the commonly found configure,
make and make install sequence. SWI-Prolog should be
installed before building this package. If SWI-Prolog is not installed
as pl, the environment variable PL
must be set to
the name of the SWI-Prolog executable. Installation is now accomplished
using:
% ./configure % make % make install |
This installs the Prolog library files in $PLBASE/library
,
where
$PLBASE
refers to the SWI-Prolog `home-directory'.
Run the file setup.pl
by double clicking it. This will
install the required files into the SWI-Prolog directory and update the
library directory.