Hello,

I have a problem using default_primary_key_generator. I'm new to RDBO,
so please be clement. ;o) It' really complex and so not easy to learn.
(Well, for me.)

I am writing a "generic" application for data synchronisation. The sync
script itself does not "know" anything about the underlying schema,
column names etc. This means, it cannot make use of column accessors and
such things. (In fact it does occasionally, but let's ignore this at
this point.) I have no influence on the DB schema, so I cannot make any
changes there.

The application maps source and target attribute names using a "map
file", so they can be configured outside without any changes to the
code, and loads the required information about the database schema,
where needed, from a Rose::DB::Object schema created by RDBO::Loader.
For example, it loads the column names from the row object to be sure
that the data hash uses correct key names before storing it into the
database. So I can use a case insensitive map file.

As the database schema (it's Oracle 9i, by the way, but I don't think
this really matters) does not have any triggers for "auto increment"
columns, I have created a generic default_primary_key_generator()
function which is used for all tables. This function loads the entry
with the max id (using a simple sort), increments this value and returns
it. (In fact the content of the primary key field is a string, but I
think this doesn't matter either.)

Now, the current task I am working on is to synchronize an object that
exists on both sides, the source (LDAP in this case) and the database.
At this point, lot's of work is done to see if there are any changes, so
I'm pretty sure there are. :o) I have a hash now where the changes are
stored. Some of the data affects related tables.

Example:

{
          'CMP_NETWORK' => {
                             'NICADDRESS' => '111122223331'
                           },
          'HWLASTSCANDATE' => '2008011518:02:00'
}

Currently, I try this to load the row from the database and store the
changes to the RDBO object:

my $row     = $schema->new(
                      db   => $dbh,
                      %{
                          $self->_prepare_data( $schema, {
$self->tableset( 'idfield' ) => $attrs{'dn'} } )
                      }
                  )->load;
$row->init( %$data );

(Where _prepare_data is the function to correctly map column names to
hash keys and tableset() is a "driver function" that provides access to
some config data for the current table. Please remember, this is a
generic application which does not only synchronize databases.)

Now, wenn storing the changes with $row->save( cascade => 1 ), the
changes are stored as expected, _but_, a new "primary key" value is
generated. So, for each update of this object, the value of the key
field in the related table (CMP_NETWORK in this case) is incremented.

I have tried other ways, f. e. using a foreach() construct to iterate
over the keys in the $data hash(ref), but as I can't be sure that
there's only one sublevel, I would have to use a recursive function to
do this. I'm sure there's a better way to do this. I have also tried to
add CMP_NETWORK to the 'with' param in load().

Here's my primary key generator:

sub default_primary_key_generator {
    my( $class, $db ) = @_;

    my $key     = $class->meta->primary_key->column_names->[0];
    
    my %params  = (
        query => [
            $key => { like => 'MAT.'.$key.'.%' },
        ],
        sort_by => $key . ' DESC',
        limit   => 1,
    ); 
    
    my $max_id = Rose::DB::Object::Manager->get_objects( 
                     object_class => $class,
                     %params 
                 );
    
    my $current = 0;
    
    if ( $max_id->[0]->{$key} =~ m|^MAT\..*\.(\d+)$| ) {
        $current = $1;
    }
    $current++;
    
    my $id = 'MAT.'.$key.'.'.sprintf( '%06d', $current );

    return $id;
    
}   # --- end sub default_primary_key_generator ---


As you can see, the content of the key field is generated using the very
simple schema 'MAT.<FIELDNAME>.<NUMBER>'. I _can_ be sure that there's
only one primary key field in each table, and I _can_ be sure that this
schema is the same in any table I use.

I'm afraid I'm a bit blind at this point, so any help is VERY
appreciated. I have digged this mailing list very deep within the last
weeks and found it very helpful. :o) Many of my problems so far could be
solved by doing a search here.

Greetings, Bianka

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to