use DBIx::Class::ResultSetColumn;
use base qw/DBIx::Class/;
-use Data::Dumper; $Data::Dumper::Indent = 1;
-
__PACKAGE__->load_components(qw/AccessorGroup/);
__PACKAGE__->mk_group_accessors('simple' => qw/result_source result_class/);
$attrs->{alias} ||= 'me';
- bless {
+ # XXXX
+ # Use a named hash here and bless afterwards to avoid a huge performance hit
+ # in perl 5.8.8-5+ FC5 and later, and possibly other distributions.
+ #
+ # See https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=196836 for more
+ # information.
+ my $self = {
result_source => $source,
result_class => $attrs->{result_class} || $source->result_class,
cond => $attrs->{where},
-# from => $attrs->{from},
-# collapse => $collapse,
count => undef,
pager => undef,
attrs => $attrs
- }, $class;
+ };
+
+ bless $self, $class;
+
+ return $self;
}
=head2 search
columns => [qw/name artistid/],
});
+For a list of attributes that can be passed to C<search>, see L</ATTRIBUTES>. For more examples of using this function, see L<Searching|DBIx::Class::Manual::Cookbook/Searching>.
+
=cut
sub search {
}
}
- unless ($self->_is_unique_query($attrs->{where})) {
- carp "Query not guaranteed to return a single row"
- . "; please declare your unique constraints or use search instead";
- }
+# XXX: Disabled since it doesn't infer uniqueness in all cases
+# unless ($self->_is_unique_query($attrs->{where})) {
+# carp "Query not guaranteed to return a single row"
+# . "; please declare your unique constraints or use search instead";
+# }
my @data = $self->result_source->storage->select_single(
$attrs->{from}, $attrs->{select},
An accessor for the primary ResultSource object from which this ResultSet
is derived.
+=head2 result_class
+
+=over 4
+
+=item Arguments: $result_class?
+
+=item Return Value: $result_class
+
+=back
+
+An accessor for the class to use when creating row objects. Defaults to
+C<< result_source->result_class >> - which in most cases is the name of the
+L<"table"|DBIx::Class::Manual::Glossary/"ResultSource"> class.
+
=cut
"' has no such relationship $rel")
unless $rel_obj;
- my $rs = $self->search(undef, { join => $rel });
- my ($from,$seen) = $rs->_resolve_from;
+ my ($from,$seen) = $self->_resolve_from($rel);
- my $join_count = $self->{attrs}{seen_join}{$rel};
- my $alias = $join_count ? join('_', $rel, $join_count+1) : $rel;
+ my $join_count = $seen->{$rel};
+ my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
$self->result_source->schema->resultset($rel_obj->{class})->search_rs(
undef, {
+ %{$self->{attrs}||{}},
+ join => undef,
+ prefetch => undef,
select => undef,
as => undef,
alias => $alias,
where => $self->{cond},
- _parent_from => $from,
seen_join => $seen,
+ from => $from,
});
};
}
+sub _resolve_from {
+ my ($self, $extra_join) = @_;
+ my $source = $self->result_source;
+ my $attrs = $self->{attrs};
+
+ my $from = $attrs->{from}
+ || [ { $attrs->{alias} => $source->from } ];
+
+ my $seen = { %{$attrs->{seen_join}||{}} };
+
+ my $join = ($attrs->{join}
+ ? [ $attrs->{join}, $extra_join ]
+ : $extra_join);
+ $from = [
+ @$from,
+ ($join ? $source->resolve_join($join, $attrs->{alias}, $seen) : ()),
+ ];
+
+ return ($from,$seen);
+}
+
sub _resolved_attrs {
my $self = shift;
return $self->{_attrs} if $self->{_attrs};
my $source = $self->{result_source};
my $alias = $attrs->{alias};
- # XXX - lose storable dclone
- my $record_filter = delete $attrs->{record_filter};
- #$attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
-
- $attrs->{record_filter} = $record_filter if $record_filter;
-
$attrs->{columns} ||= delete $attrs->{cols} if exists $attrs->{cols};
if ($attrs->{columns}) {
delete $attrs->{as};
} elsif (!$attrs->{select}) {
- $attrs->{columns} = [ $self->{result_source}->columns ];
+ $attrs->{columns} = [ $source->columns ];
}
-
- $attrs->{select} ||= [
- map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}}
- ];
- $attrs->{as} ||= [
- map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}}
- ];
+
+ $attrs->{select} =
+ ($attrs->{select}
+ ? (ref $attrs->{select} eq 'ARRAY'
+ ? [ @{$attrs->{select}} ]
+ : [ $attrs->{select} ])
+ : [ map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}} ]
+ );
+ $attrs->{as} =
+ ($attrs->{as}
+ ? (ref $attrs->{as} eq 'ARRAY'
+ ? [ @{$attrs->{as}} ]
+ : [ $attrs->{as} ])
+ : [ map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}} ]
+ );
my $adds;
if ($adds = delete $attrs->{include_columns}) {
}
if ($adds = delete $attrs->{'+select'}) {
$adds = [$adds] unless ref $adds eq 'ARRAY';
- push(@{$attrs->{select}}, map { /\./ || ref $_ ? $_ : "${alias}.$_" } @$adds);
+ push(@{$attrs->{select}},
+ map { /\./ || ref $_ ? $_ : "${alias}.$_" } @$adds);
}
if (my $adds = delete $attrs->{'+as'}) {
$adds = [$adds] unless ref $adds eq 'ARRAY';
}
$attrs->{from} ||= [ { 'me' => $source->from } ];
- if ($attrs->{_parent_from}) {
- push @{$attrs->{from}}, @{delete $attrs->{_parent_from}};
- }
if (exists $attrs->{join} || exists $attrs->{prefetch}) {
-
my $join = delete $attrs->{join} || {};
if (defined $attrs->{prefetch}) {
);
}
- push(@{$attrs->{from}},
- $source->resolve_join($join, $alias, { %{$attrs->{seen_join}||{}} })
- );
+ $attrs->{from} = # have to copy here to avoid corrupting the original
+ [
+ @{$attrs->{from}},
+ $source->resolve_join($join, $alias, { %{$attrs->{seen_join}||{}} })
+ ];
}
$attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
if ($attrs->{order_by}) {
- $attrs->{order_by} = [ $attrs->{order_by} ] unless ref $attrs->{order_by};
+ $attrs->{order_by} = (ref($attrs->{order_by}) eq 'ARRAY'
+ ? [ @{$attrs->{order_by}} ]
+ : [ $attrs->{order_by} ]);
} else {
- $attrs->{order_by} ||= [];
+ $attrs->{order_by} = [];
}
my $collapse = $attrs->{collapse} || {};
return $self->{_attrs} = $attrs;
}
-sub _resolve_from {
- my ($self) = @_;
- my $source = $self->result_source;
- my $attrs = $self->{attrs};
-
- my $from = [ @{$attrs->{_parent_from}||[]} ];
-# || [ { $attrs->{alias} => $source->from } ];
-
- my $seen = { %{$attrs->{seen_join}||{}} };
-
- if ($attrs->{join}) {
- push(@{$from},
- $source->resolve_join($attrs->{join}, $attrs->{alias}, $seen)
- );
- }
-
- return ($from,$seen);
-}
-
sub _merge_attr {
my ($self, $a, $b) = @_;
- return $b unless $a;
+ return $b unless defined($a);
+ return $a unless defined($b);
if (ref $b eq 'HASH' && ref $a eq 'HASH') {
foreach my $key (keys %{$b}) {
You can create your own accessors if required - see
L<DBIx::Class::Manual::Cookbook> for details.
-Please note: This will NOT insert an C<AS employee_count> into the SQL statement
-produced, it is used for internal access only. Thus attempting to use the accessor
-in an C<order_by> clause or similar will fail misrably.
+Please note: This will NOT insert an C<AS employee_count> into the SQL
+statement produced, it is used for internal access only. Thus
+attempting to use the accessor in an C<order_by> clause or similar
+will fail miserably.
+
+To get around this limitation, you can supply literal SQL to your
+C<select> attibute that contains the C<AS alias> text, eg:
+
+ select => [\'myfield AS alias']
=head2 join