(Oops, accidentally sent an imcomplete message last time
On 8/5/06 9:44 AM, Danial Pearce wrote:
> On 8/5/06, John Siracusa <[EMAIL PROTECTED]> wrote:
>> I've rearranged the interface to this stuff a little bit in SVN, but
>> the results should still take care of your situation.  If you get a
>> chance, try the SVN version and let me know if it correctly makes the
>> foo->bar relationship "optional" by default.
> 
> Mine is dying when you have a completely new object, and you have your
> new object to create a new object in the relationship also.

Cascade on save really doesn't come into play with brand new objects.
They're handled by the existing get_set_on_save methods.

> Consider the following tables:
> 
> create table foo ( id serial not null, foo text );
> create table bar ( foo_id int not null references foo(id), bar text);

Neither has a primary key, and RDBO requires every table to have one.  But
I'll assume you meant this:

  create table foos
  (
    id serial not null primary key,
    foo text
  );
  
  create table bars
  (
    foo_id int not null primary key references foos (id),
    bar text
  );

Given those tables, this is what the Loader makes of them:

  package Bar;
  ...
  __PACKAGE__->meta->setup
  (
    table   => 'bars',
    columns => 
    [
      foo_id => { type => 'integer', not_null => 1 },
      bar    => { type => 'text' },
    ],
  
    primary_key_columns => [ 'foo_id ' ],
  
    foreign_keys =>
    [
      foo => 
      {
        class => 'Foo',
        key_columns => { foo_id => 'id' },
      },
    ],
  );
  
  package Foo;
  ...
  __PACKAGE__->meta->setup
  (
    table   => 'foos',
    columns => 
    [
      id  => { type => 'serial', not_null => 1 },
      foo => { type => 'text' },
    ],
  
    primary_key_columns => [ 'id' ],
  
    relationships =>
    [
      bars => 
      {
        class       => 'Bar',
        key_columns => { id => 'foo_id' },
        type        => 'one to many',
      },
    ],
  );

Notice that it's made the foo->bar relationship a one-to-many.  It's not
quite smart enough to see that both foo.id and bar.foo_id are unique keys
(primary keys, in fact), making it a one-to-one relationship.

I've updated the Loader in SVN to correctly detect one-to-one relationships,
so now it produces a Foo class like this:

  package Foo;
  ...
  __PACKAGE__->meta->setup
  (
    table   => 'foos',
    columns => 
    [
      id  => { type => 'serial', not_null => 1 },
      foo => { type => 'text' },
    ],
  
    primary_key_columns => [ 'id' ],
  
    relationships =>
    [
      bar => 
      {
        class      => 'Bar',
        column_map => { id => 'foo_id' },
        type       => 'one to one',
      },
    ],
  );

(Note that I changed "key_columns" to "column_map" too.)

Now for the code:

  my $bar = Bar->new;
  my $foo = Foo->new;
  $foo->bar($bar);
  $foo->bar->bar('some text');
  $foo->save;

This now runs successfully, executing the following SQL:

  # Save the foo row
  INSERT INTO foos (foo, id) VALUES (NULL, 1);

  # Check to see if $bar already exists in the database.
  # (In this case, it doesn't.)
  SELECT bar, foo_id FROM bars WHERE foo_id = 1

  # Add the bar row
  INSERT INTO bars (bar, foo_id) VALUES ('some text', 1);

Notice that the "cascade" flag is not used at all.  If it were added:

  $foo->save(cascade => 1);

it would not alter the SQL at all, nor would it add any more queries.  It
would, however, check to see if $bar has unsaved changes.  It doesn't (it
was just saved) so $bar does not need to be (re)save()d.

-John



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Rose-db-object mailing list
Rose-db-object@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/rose-db-object

Reply via email to