rgatliff has asked for the wisdom of the Perl Monks concerning the following question:

My recent study of Damian Conway's "Object Oriented Perl" has proven useful for a current project I am working on. I am dealing with a database of just over 300k records (account information for a high volume site) which I have to constantly query with select statements looking for repeats on account creation etc. It would appear from my novice experience that a better way to structure the data is in an object manner and maintain persistent objects for the current information. All documentation I have read recommend using the Data::Dumper and pushing the data to a Db using the Persistence::Object::Postgres module. I would like to keep the current DB structure and not serialize the data as other non-perl applications will read from this. Is it possible to push the oid to the DB and somehow parse the varables to insert them into seperate colums? Anyone have any recommendation on sources of information for this? Any help would be greatly appreciated. Thanks.

Replies are listed 'Best First'.
Re: Object Persistence to PostGRESQL
by chromatic (Archbishop) on Apr 01, 2001 at 05:40 UTC
    If you want to treat each record as an object (especially as a blessed hash), you can use the techniques in my DBI article to insert and select data very quickly and easily.

    (To be fair, there are also some CPAN modules which are finer-grained than just serializing a data structure and dumping the results in a LONG column. Class::Tangram first comes to mind, though there are many others.)

Re: Object Persistence to PostGRESQL
by lachoy (Parson) on Apr 01, 2001 at 17:39 UTC

    While the Postgres support isn't 100% tested yet, you might want to check out SPOPS. (Postgres support will be in the next version but you can get a stable version from CVS or by contacting me.) You can use it to retrofit existing data and you only have to create a configuration file (no code!) to model your data.

    I'll be happy to give examples if you'd like to see them but don't want to create a lengthy post for something that might not be useful to you.

    Chris
    M-x auto-bs-mode

      This direction has proven very useful, thanks! I will get the stable v from CVS. Any examples would be greatly appreciated as I find they greatly accelerate my learning. Thanks again for taking the time to reply to a novice perl guy.

        Okay, this is from one of the examples in the distribution modified for posting here (and to use Pg-specific stuff):

        #!/usr/bin/perl use strict; use DBI; use SPOPS::Configure::DBI; use Data::Dumper qw( Dumper ); { # Set these as appropriate my $dsn = 'DBI:Pg:dbname=test'; my $user = 'postgres'; my $pass = 'postgres'; my $db = DBI->connect( $dsn, $user, $pass, { AutoCommit => 1, RaiseError => 1, PrintError => 1 }); die "Cannot connect ($DBI::errstr)" unless ( $db ); # Table we're using for the example -- go ahead and create it my $fb_table = <<SQL; CREATE TABLE fatbomb ( fatbomb_id SERIAL, name VARCHAR(100) NULL, calories INT NULL, cost VARCHAR(10) NULL, servings INT DEFAULT 15, PRIMARY KEY ( fatbomb_id ) ) SQL eval { $db->do( $fb_table ) }; die "Cannot create table! Error: $@" if ( $@ ); # This is the SPOPS configuration -- typically you'd have this in # a file and process it once when your application starts my $spops = { fatbomb => { isa => [ qw/ SPOPS::DBI::Pg SPOPS::DBI / ], class => 'My::ObjectClass', field => [ qw/ fatbomb_id calories cost name servings / ], no_insert => [ qw/ fatbomb_id / ], base_table => 'fatbomb', id_field => 'fatbomb_id', increment_field => 1, skip_undef => [ qw/ servings / ], sql_defaults => [ qw/ servings / ], }, }; SPOPS::Configure::DBI->process_config({ config => $spops, require_isa => 1 }); # Poof! Our class now exists and we can call a class method on # it. This method is normally called when your application starts # up. My::ObjectClass->class_initialize; # ...and we can also create an object, fill it with info # and save it to the data store. my $object = My::ObjectClass->new; $object->{calories} = 1500; $object->{cost} = '$3.50'; $object->{name} = "Super Deluxe Jumbo Big Mac"; my $fb_id = eval { $object->save({ db => $db }) }; if ( $@ ) { my $ei = SPOPS::Error->get; die "Error found! ($@) Error information: ", Dumper( $ei ), "\n"; } # Show the ID returned and that the 'servings' property is now # filled in (we defined it with a DEFAULT and identified it in the # configuration in 'sql_defaults'. Also note that properties # are available as hash keys, which allows our favorite # interpolation rather than using get/set method calls. print "Object saved ok!\n", "Object ID: $fb_id\n", "Servings: $object->{servings}\n\n"; # Now re-fetch this object with the ID we got undef $object; my $new_object = eval { My::ObjectClass->fetch( $fb_id, { db => $db } ) }; if ( $@ ) { my $ei = SPOPS::Error->get; die "Error found! ($@) Error information: ", Dumper( $ei ), "\n"; } print "The next set of values (from re-fetched object) ", "should match that above:\n", "Object ID: $new_object->{fatbomb_id}\n", "Servings: $new_object->{servings}\n"; # Select all objects from the table that match critieria my $all_objects = eval { My::ObjectClass->fetch_group({ where => 'calories > 1000' }) }; foreach my $found_object ( @{ $all_objects } ) { print "I am $found_object->{name} and have ", "$found_object->{calories} calories.\n"; } # Cleanup $db->do( 'drop table fatbomb' ); $db->do( 'drop sequence fatbomb_fatbomb_id_seq' ); $db->disconnect; }

        I just tested this example with the latest code from CVS -- if you checked it out earlier do a cvs update in the directory openinteract/SPOPS/SPOPS/DBI/ since I fixed a small (but important!) bug.

        Hope this was useful!

        Chris
        M-x auto-bs-mode