4ODS User"s Guide


Introduction

4ODS is am implementation of the ODMG Object Data Standard v 3.0 in python. 4ODS currently implements a beta version of its own file storage, however it is not transactional, nor is it concurrent. 4ODS does support backends that are transactional and concurrent through SQL database for. 4ODS generates persistent stub classes from an ODL file. These classes are used as any other python class is used, except when commit is called on the current transaction, changes are persisted into the database. Objects can be fetched from the database using the ODS binding mechanisim, the ODS extent mechanisim, or simple OQL queries. 4ODS supports OIF for both input and output, for all meta data types supported by the backends.

ODL datatypes

The following list is of supported datatypes defined by the ODMG

The following list is of unsupported datatypes defined by the ODMG

The following list is of extended datatypes not defined by the ODMG but included in 4ODS

Unimplemented portions of the ODMG specification

Besides the above mentioned datatypes that are not supported, the following is a list of unsupported features defined by the ODMG specification.

4ODS tools

4odb_clean(.bat)
A command line tool to remove unreferencible objects from the database. An unreferenceible object is an object that cannot be reached by binding, extents or traversal. Currently not implemented
4odb_clear(.bat)
A command line tool to remove all instance data from an ODS database. This will not remove any metadata information. This command takes one parameter, the name of the database.
4odb_create(.bat)
A command line tool to initialize a new ODS database. This tool does not add any metadat information (see OdlParse) but sets up all of the system tables. This tool takes one parameter, then name of the database
4odb_destroy(.bat)
A command line tool to completely remove an ODS database from the system. This tool takes one parameter, then name of the database
4odb_dig(.bat)
A command line tool to view the contents in a proprietary format. Some relationships can be traversed. Run with no paramters to see help.
4odb_grant(.bat)
A command line tool to grant access to a database. Run without arguments to see help.
4odb_metadig(.bat)
A command line tool to view the metadata structure of a ODS database. Run with -o option to dump ODL of the database.
4odb_odmsdump(.bat)
A Commmand line tool to dump a 4ODS database to OIF.
4odb_odmsload(.bat)
A Commmand line tool to initial a 4ODS database from OIF. 4odb_create.py must be called first.

OdlParse

OdlParse is used to inialize the metadata structure of a database and/or generate the pstubs. the following command line options are supported

OdlParse [-p [--package=<package>]] [-i [-f]| -u] [-d] [-c] db_name <odl_source>
-p
Generate pstubs
--package
Import from specified package
-i
Initialze a new databases metadata. Calls 4dob_destroy and 4odb_create with the specified database name
-f
Don't ask before destroying an old database.
-u
Update an existing databases metadata. Name resolution between current metadata and new metadata is not supported.
-d
Generate debugging code in the pstubs
-c
Run ODL through a C preprocessor before ODL compilation. This is only supported on Unix.

Database names

All tools and the Database interface require a database name. The following is the supported format for database names

ods:<username>/<password>@<host>:<port>:dbname

or

dbname

If the string starts with ods: then it will be broken into pieces and used to connect to the back end database. All fields except dbname are optionaly. If not, the string will be passed as is to the local database.

How to change the storage adapter

4ODS, except for the beta Dbm Adapter, relies on a SQL backend for the actual storage of objects. By default, 4ODS uses the Postgres adapter. In order to use the Postgres adapter, PyGreSQL must be installed on the machine, and the user of 4ODS must have access to a PostgreSQL database. Other adapters include an Oracle Adapter (DCORacle and access to an Oracle Database required) and the Dbm adapter (no additional modules needed. One note on the Dmb adapter, it is in beta stage with no support for proper transaction or concurrency. If used in a muti-threaded or multi-process application, the application must take care of concurrency and transaction sysmantics.

How to use the system (a very basic walk through)

First create a ODL file that represents what you want to store in test.odl

module simple {
  class person {
    attribute string name;
    attribute double weight;
    relationship Person spouse inverse Person ::spouse_of;
    relationship Person spouse_of inverse Person ::spouse;
    relationship list<Person> children  inverse Person ::child_of;
    relationship Person child_of inverse Person ::children;
  };
  class employee (extends person) {
    attribute string id;
  };
};

Now create a new database and initialize

 #OdlParse -ifp test test.odl

Now write some python code to do stuff with these people

#!/usr/bin/python

#Every thing that is persisten must be done inside a transaction and open database
from Ft.Ods import Database
db = Database.Database()
db.open('test')

tx = db.new()
tx.begin()

#Create a new instance of some objects
import person
import employee
dad = employee.new()
mom = person.new()
son1 = person.new()
son2 = person.new()
daughter = person.new()

#Set some attributes
dad.name = "Pops"
mom.name = "Ma"
son1.name = "Joey"
son2.name = "Bobby"
daughter.name = "Betty"
dad.weight = 240.50

#We can set attributes not defined in the ODL but they will not persist
mom.address = "1234 Error Way"


#Set some relationships

#First set a one to one relationship
dad.spouse = mom

#Or we could have done it via the ODMG spec
#dad.form_spouse(mom)

#Add some children to the dad (our data model does not let mom have children.  We'd need a family struct (left up to the reader)

dad.add_children(son1)
#We can create relationships both ways
son2.form_child_of(dad)

#Shortcut for adding
dad.children = daughter

#Now root the family to some top level object.
db.bind(dad,"The Fam")

#Make it so
tx.commit()

#Out side of a transaction we can still access the objects.
#However, any changes we make will not persist.
#NOTE, because 4ODS caches relationships, any relationships that were not traversed during the
#transaction, cannot be traversed now because an object cannot be loaded from the db outside
#of a transaction.
print dad.name

#Start a new tx to fetch

tx = db.new()
tx.begin()

newDad = db.lookup("The Fam")

print newDad.name
print newDad.children[0].name
print newDad.spouse

#Discard this transaction
tx.abort()

Ft/Ods/test_suite and Ft/Ods/demo are good places to look for more examples