> > 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 > );
Apologies. You are correct. I did mean to have primary key on those. > 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.) I was using add_relationships() to manually set my type to "one to one" anyway. I was also using column_map. > 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. Yep, works for me now too. Thanks a bunch! I also tested your fix for not running the UPDATE sql where there were no fields to update, and it is also work a treat. Thanks again. -- "Cats are smarter than dogs. You can't get eight cats to pull a sled through snow." - Jeff Valdez ------------------------------------------------------------------------- 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