I'd like to get some feedback on an idea for a new DBI wrapper, or a
lightweight object-relational mapping if you prefer to look at it that way.
The main goal is ease of writing a simple database app. The thing that
distinguishes it from all the other DBI wrappers out there is that the database
schema is created/changed as you add data - when developing an application you
can just use new fields in your objects/columns to your tables and they get
created in the database. Also, rows are tied to the database so that simply
assigning to them changes the database. I have a lot of the code ready and
working, it doesn't quite do everything described below but it's been used in a
few projects already.

I'd like some comments about...

1) Is there another module that does the same thing? (DBIx::Simple and
DBIx::Wrapper for example help but definitely leave you to do manually a lot of
the things this module takes care of; on the other hand, Class::DBI, Alzabo and
Tangram do a whole lot more than this module but are too heavyweight for simple

2) What would be a good name? Some ideas are DBIx::Flexible,
DBIx::RapidPrototype, DBIx::VerySimple, DBIx::SimpleORDB, ... ?

3) Any suggestions for changes to the interface? Some areas that are not
completely fleshed out are error handling (die/global error variable/stderr),
inheritance to create a database-stored object (how is it instantiated from the
database), etc. I'd also like to somehow borrow the map_* idea from

-Alex Izvorski


$db = DBIx::Flexible->connect(...); # stuff gets passed to DBI

$people = $db->table('people'); # create a people table if it doesn't exist

$people->insert(+{ name => 'John Smith', phone => '000 000 0000', height => 5.75 }); # adds name, phone, height columns to the people table, and then inserts a row with the data we gave

$person = $people->select(+{ name => 'John Smith' }); # optionally indexes people by name if not already indexed, then fetches the row we just put in (this will return array of rows if requested)

print $person->{phone};
print $person->get_phone(); # this also works

$person->{phone} = '800 000 000'; # this actually changes the phone column in the database
$person->set_phone('800 000 000'); # so does this

$people->set_condition('phone', sub { return ($_[0] =~ m/\d\d\d \d\d\d \d\d\d\d/); }); # set a perl subroutine to check phone values

$person->set_phone('0'); # this fails (with a die or an error message)

$person->{hobbies} = [ 'Swimming', 'Jogging' ]; # this adds a new column 'hobbies', packs the data using Storable, and puts it there

$schema = $people->get_schema(); # this returns something like the following
# $schema = +{
# fields =>
# +{
# _id => +{ ftype => 'id' },
# name => +{ ftype => 'text' },
# phone => +{ ftype => 'text', fconditions => [ CODE(...) ] },
# height => +{ ftype => 'float' },
# hobbies => +{ ftype => 'storable' },
# },
# keys => [ '_id', 'name' ]
# };

push(@{$schema->{keys}}, 'phone'); # this creates a new index for the phone

delete $schema->{fields}->{hobbies}; # this deletes the hobbies column

# creating a database-stored object
package MyPerson;
@ISA = qw(DBIx::Flexible::Row);

$schema->{package} = 'MyPerson'; # any rows returned by select etc from this point on are instances of MyPerson that also inherit the tied-hashref and get/set method behaviour of normal rows

$db->freeze_schema(); # prevent modification of schema for all tables in db


DBIx::Flexible is a module that would help with using a database for simple,
rapid-prototyping applications that would otherwise use Storable, Data::Dumper,
a DBM or something else like that to store their data. In the typical case,
there is just one table for each kind of entity in the application (usually
just one table), tables are never joined (i.e. we never do a select from
multiple tables, although tables may have keys that refer to other tables),
there are essentially no constraints on the data imposed in the database itself
(although there may be constraints in the application code), and the exact
fields and indexes change all the time as the application is being developed.

The main goal is that it should be almost as easy to use a database as it is a
structure in memory. To that end:

* rows are returned as hashrefs that also have "magic" accessor methods for
each field

* selects take an example hashref with the fields we want to match

* updating a row value should immediately update the database

* the database schema should be updated as needed, on the fly, by adding and
dropping columns and indexes (with an option to freeze the schema)

* values should be packed/unpacked as appropriate

* values should be verified when updating using perl callbacks

* it should not be necessary to write any SQL most of the time

This package is meant to be somewhere between a full object-relational mapping
system (which would require you to subclass it for each object, and to define
schema in advance) and a dbi wrapper (which usually just saves writing sql by
hand). You can still subclass it for each object if you wish, but you don't
really have to define anything.

Limitations (in the interest of simplicity):

* no way to get part of a row, you get an entire row

* no way to iterate over rows, you get the entire result set at the same time

* no way to do table joins when select'ing, or to model a one/one, one/many or
many/many relationship [MAY be added later]
(of course there is nothing that prevents you from putting a primary key from
one table in a field in another, but this module wouldn't know or care that
they are related.

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupdbi-users @
postedMar 11, '04 at 3:53a
activeMar 11, '04 at 3:53a

1 user in discussion

Alex Izvorski: 1 post



site design / logo © 2022 Grokbase