[Dbix-class] Possible trouble with ResultSet::new_result, was: Why are these two relations different?

John Napiorkowski jjn1056 at yahoo.com
Thu May 4 08:28:29 CEST 2006


Just a few more things I discovered before totally
giving up on this.

Seems that adding a where condition pretty much
anywhere causes the problem I've outlined in this
post.  So here is the most simple test case I've found
so far:

Given two tables, Parent and Child, where child has a
foreign key to parent.

Table Parent
 parent_id, Primary key
 [etc]

Table Children
 child_id, Primary key
 parent_id, FK to Parent.parent_id
 age, int not null
 [etc]

and I create the DBIx schemas as so:

package Schema::Parent;
use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/ PK::Auto Core /);
__PACKAGE__->table('Parent');
__PACKAGE__->add_columns(qw/parent_id [etc]/);
__PACKAGE__->primary_key(qw/parent_id/);
__PACKAGE__->has_many('Children'=>'Schema::Children');

package Schema::Children;
use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/ PK::Auto Core /);
__PACKAGE__->table('Children');
__PACKAGE__->add_columns(qw/child_id [etc]/);
__PACKAGE__->primary_key(qw/child_id/);

Then I connect to the schema:

my $schema = Schema->connect;
my $parents = $schema->resultset('Parents');
my $parent = $parents->find({parent_id=>1});

$parent->search_related('Children')->create([valid
attrs]); #Works no trouble

$parent->search_related('Children', {ANY VALID WHERE
CONDIION})->create([valid attrs]); #DIES

Seems to me the call to ->create should work whether
the related condition is simple or has additional
conditions on it, but maybe I am just not
understanding the DBIx way.  Is there a more 'right'
way to do this.  Any enlightment is appreciated before
I return to SQL :)

Here is my attempts to understand this:  As I outlined
in the previous post the call to ResultSet::new_result
seems to be the root of this trouble.  In that method
there is a call:

my $obj = $self->result_class->new(\%new);

and in the second ->create from the example above  the
%new hash will have things like '-and' in it as keys. 
This causes the application to die because eventually
somewhere ->column_info gets called for '-and' and of
course there is no column called that.  See more
details on how this hash is created in the post below.

I can't figure out what module/method that
...->new(\%new) is referring to.  It's not referring
to the new method in ResultSet.pm but I can't trace it
from here.

Hope this helps someone point me in the right
direction. Even if you can just tell me what
package/method that ->new(...) is referring to that
would help me a lot.




--john

--- John Napiorkowski <jjn1056 at yahoo.com> wrote:

> I got some more details that I hope can help us
> understand the problem.
> 
> Given the schema setup the way I described it I did
> a
> Data::Dumper to try and figure out what is the main
> difference between resultsets returned by the two
> different relations:
> 
> use Data::Dumper;
> 
> print Dump ($documents->root_folders_a);
> print Dump ($documents->root_folders_b);
> 
> Doing a diff on the two leads to just two minor
> differences.  Under the
> $documents->root_folders_a->{attrs}->{where} I get:
> 
> 'where' => {
>    'me.document_id' => '2'
> }
> 
> Whereas with
> $documents->root_folders_b->{attrs}->{where} I get:
> 
> 'where' => {
> 
>    '-and' => [
>       {
>          'me.document_id' => '2'
>       },
>       {
>          'parent_id' => \'IS NULL'
>       }
>    ]
> 
> }
> 
> Which makes total sense since the second relation
> has
> an addition contraint.  Now it's this '-and' thing
> that is causing the program to die when column_info
> gets called (since there is no column called
> '-and'.) 
> So I looked back to ResultSet::new_result() which is
> where I think the error is occuring.  In that
> new_result sub there are some lines (edited for
> clarity):
> 
> foreach my $key (keys %{$self->{cond}||{}})
> {
>    $new{$1} = $self->{cond}{$key} 
>     if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/);
> }
> 
> Here, $self->{cond} appears to be a ref to
> $self->{attrs}->{where}. So in my example for
> $documents->root_folders_b this loops over a hash
> with
> just one key in it '-and'.  For some reason this
> '-and' value matches the regex and some the %new
> hash
> ends up with a bad column name in it.
> 
> So at this point I am left with two possibilities (I
> think).  Either:
> 
> 1) $self->{cond} isn't pointing to the right thing
> (it
> should probably ref the
> ...->{attrs}->{where}->{'-and'} instead of
> ...->{attrs}->{where}.
> 
> 2) There is something wrong with this regex.
> 
> My best guess now is that the problem is more likely
> to be 1.
> 
> I'm going to look into this further, but I really
> think I'm a bit in over my head.  Is there anyone
> out
> there who knows how this is supposed to work that
> can
> point me in the right direction?
> 
> Also if I am not posting this to the correct list I
> would appreciate it if someone could let me know. 
> Thanks!
> 
> --john
> 
> 
> 
> > I don't understand why the two 'add_relationships'
> > in
> > the following behave so differently:
> > 
> > package Schema::Documents;
> > 
> > [all the normal setup for a schema]
> > 
> > __PACKAGE__->add_relationship(
> > 
> >   'root_folders_a', 
> >   'Schema::bookmarks',  
> >   {'foreign.document_id' => 'self.document_id'}, 
> > 
> > );
> > 
> > __PACKAGE__->add_relationship(
> > 
> >   'root_folders_b', 
> >   'Schema::bookmarks', 
> >   {'foreign.document_id' => 'self.document_id'}, 
> >   { where => { 'parent_id' => \"IS NULL" } }
> > );
> > 
> > sub root_folders_a
> > {
> >   my $self	= shift @_;
> >   return
> $self->related_resultset('root_folders_a');
> > }
> > 
> > sub root_folders_b
> > {
> >   my $self	= shift @_;
> >   return
> $self->related_resultset('root_folders_b');
> > }
> > 
> > my $schema = Schema->connect;
> > my $documents = $schema->resultset('Documents');
> > 
> > my $documents->root_folders_a->create({...});
> #WORKS
> > my $documents->root_folders_b->create({...});
> #DIES
> > 
> > The error I get for the second create is "No such
> > column -and".  I traced this error message to a
> > section of code in ResultSource.pm:
> > 
> > sub column_info {
> >   my ($self, $column) = @_;
> >   $self->throw_exception("No such column $column")
> >     unless exists $self->_columns->{$column};
> > [...]
> > 
> > Where it seems somebody tried to get info on the
> > '-and' clause which I guess is part of how the
> > system
> > adds the constraints.  So I traced it further back
> > to
> > find out who is passing column_info such dubious
> > information.  I found the following in
> ResultSet.pm:
> > 
> > sub new_result {
> >   my ($self, $values) = @_;
> >  [....]
> >   my %new = %$values;
> > 
> > #Right now %new is a hash of all the real columns
> > 
> >   my $alias = $self->{attrs}{alias};
> >   foreach my $key (keys %{$self->{cond}||{}}) {
> >     $new{$1} = $self->{cond}{$key} if ($key =~
> > m/^(?:\Q${alias}.\E)?([^.]+)$/);
> >   }
> > 
> > #but after the loop above it's got the '-and' and
> > some
> > #other stuff.
> > 
> > [...]
> > }
> > 
> > I don't understand the system well enough to
> > determine
> > if this area is the cause of the trouble.  This is
> > as
> > far as I could get.  Now I think for consistency
> > that
> > both relations should be able to call methods and
> > such
> > with equal results.  Why does it care if the
> > relation
> > is very simple or more complex?
> > 
> > Any thought or suggestions would be appreciated.
> > 
> > --john
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> > __________________________________________________
> > Do You Yahoo!?
> > Tired of spam?  Yahoo! Mail has the best spam
> > protection around 
> > http://mail.yahoo.com 
> > 
> > _______________________________________________
> > List:
> >
>
http://lists.rawmode.org/cgi-bin/mailman/listinfo/dbix-class
> > Wiki: http://dbix-class.shadowcatsystems.co.uk/
> > IRC: irc.perl.org#dbix-class
> > SVN:
> >
>
http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/
> > 
> 
> 
> __________________________________________________
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam
> protection around 
> http://mail.yahoo.com 
> 
> _______________________________________________
> List:
>
http://lists.rawmode.org/cgi-bin/mailman/listinfo/dbix-class
> Wiki: http://dbix-class.shadowcatsystems.co.uk/
> IRC: irc.perl.org#dbix-class
> SVN:
>
http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/
> 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the Dbix-class mailing list