A ResultSource is a component of a schema from which results can be directly
retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
+Basic view support also exists, see L<<DBIx::Class::ResultSource::View>.
+
=head1 METHODS
=pod
=item default_value
Set this to the default value which will be inserted into a column
-by the database. Can contain either a value or a function. This is
-currently only used by L<DBIx::Class::Schema/deploy>.
+by the database. Can contain either a value or a function (use a
+reference to a scalar e.g. C<\'now()'> if you want a function). This
+is currently only used by L<DBIx::Class::Schema/deploy>.
+
+See the note on L<DBIx::Class::Row/new> for more information about possible
+issues related to db-side default values.
=item sequence
=cut
sub resolve_join {
- my ($self, $join, $alias, $seen, $force_left) = @_;
- $seen ||= {};
+ my ($self, $join, $alias, $seen, $force_left, $jpath) = @_;
+
+ # we need a supplied one, because we do in-place modifications, no returns
+ $self->throw_exception ('You must supply a seen hashref as the 3rd argument to resolve_join')
+ unless $seen;
+
$force_left ||= { force => 0 };
+
+ # This isn't quite right, we should actually dive into $seen and reconstruct
+ # the entire path (the reference entry point would be the join conditional
+ # with depth == current_depth - 1. At this point however nothing depends on
+ # having the entire path, transcending related_resultset, so just leave it
+ # as is, hairy enough already.
+ $jpath ||= [];
+
if (ref $join eq 'ARRAY') {
- return map { $self->resolve_join($_, $alias, $seen) } @$join;
+ return
+ map {
+ local $force_left->{force} = $force_left->{force};
+ $self->resolve_join($_, $alias, $seen, $force_left, [@$jpath]);
+ } @$join;
} elsif (ref $join eq 'HASH') {
return
map {
- my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
- local $force_left->{force};
+ my $as = ($seen->{$_} ? join ('_', $_, $seen->{$_} + 1) : $_); # the actual seen value will be incremented below
+ local $force_left->{force} = $force_left->{force};
(
- $self->resolve_join($_, $alias, $seen, $force_left),
+ $self->resolve_join($_, $alias, $seen, $force_left, [@$jpath]),
$self->related_source($_)->resolve_join(
- $join->{$_}, $as, $seen, $force_left
+ $join->{$_}, $as, $seen, $force_left, [@$jpath, $_]
)
);
} keys %$join;
} elsif (ref $join) {
$self->throw_exception("No idea how to resolve join reftype ".ref $join);
} else {
+
my $count = ++$seen->{$join};
- #use Data::Dumper; warn Dumper($seen);
my $as = ($count > 1 ? "${join}_${count}" : $join);
+
my $rel_info = $self->relationship_info($join);
$self->throw_exception("No such relationship ${join}") unless $rel_info;
my $type;
$force_left->{force} = 1 if lc($type) eq 'left';
}
return [ { $as => $self->related_source($join)->from,
- -join_type => $type },
+ -join_type => $type,
+ -join_path => [@$jpath, $join],
+ -join_alias => $as,
+ -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
+ },
$self->resolve_condition($rel_info->{cond}, $as, $alias) ];
}
}
#warn "$self $k $for $v";
unless ($for->has_column_loaded($v)) {
if ($for->in_storage) {
- $self->throw_exception("Column ${v} not loaded on ${for} trying to resolve relationship");
+ $self->throw_exception(
+ "Column ${v} not loaded or not passed to new() prior to insert()"
+ ." on ${for} trying to resolve relationship (maybe you forgot "
+ ."to call ->reload_from_storage to get defaults from the db)"
+ );
}
return $UNRESOLVABLE_CONDITION;
}
=cut
sub resolve_prefetch {
- my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
- $seen ||= {};
- #$alias ||= $self->name;
- #warn $alias, Dumper $pre;
+ my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
+ $pref_path ||= [];
+
if( ref $pre eq 'ARRAY' ) {
return
- map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
+ map { $self->resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
@$pre;
}
elsif( ref $pre eq 'HASH' ) {
my @ret =
map {
- $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
+ $self->resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
$self->related_source($_)->resolve_prefetch(
- $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
+ $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
} keys %$pre;
- #die Dumper \@ret;
return @ret;
}
elsif( ref $pre ) {
"don't know how to resolve prefetch reftype ".ref($pre));
}
else {
- my $count = ++$seen->{$pre};
- my $as = ($count > 1 ? "${pre}_${count}" : $pre);
+
+ my $p = $alias_map;
+ $p = $p->{$_} for (@$pref_path, $pre);
+
+ $self->throw_exception (
+ "Unable to resolve prefetch $pre - join alias map does not contain an entry for path "
+ . join (' -> ', @$pref_path, $pre)
+ ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
+
+ my $as = shift @{$p->{-join_aliases}};
+
my $rel_info = $self->relationship_info( $pre );
$self->throw_exception( $self->name . " has no such relationship '$pre'" )
unless $rel_info;
return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
$rel_source->columns;
- #warn $alias, Dumper (\@ret);
- #return @ret;
}
}