[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