use Storable;
use DBIx::Class::ResultSetColumn;
use DBIx::Class::ResultSourceHandle;
+use List::Util ();
use base qw/DBIx::Class/;
__PACKAGE__->mk_group_accessors('simple' => qw/result_class _source_handle/);
$attrs->{alias} ||= 'me';
+ # Creation of {} and bless separated to mitigate RH perl bug
+ # see https://bugzilla.redhat.com/show_bug.cgi?id=196836
my $self = {
_source_handle => $source,
result_class => $attrs->{result_class} || $source->resolve->result_class,
L<Searching|DBIx::Class::Manual::Cookbook/Searching>. For a complete
documentation for the first argument, see L<SQL::Abstract>.
+For more help on using joins with search, see L<DBIx::Class::Manual::Joining>.
+
=cut
sub search {
sub search_rs {
my $self = shift;
- my $rows;
-
- unless (@_) { # no search, effectively just a clone
- $rows = $self->get_cache;
- }
-
my $attrs = {};
$attrs = pop(@_) if @_ > 1 and ref $_[$#_] eq 'HASH';
my $our_attrs = { %{$self->{attrs}} };
my $having = delete $our_attrs->{having};
my $where = delete $our_attrs->{where};
+ my $rows;
+
+ my %safe = (alias => 1, cache => 1);
+
+ unless (
+ (@_ && defined($_[0])) # @_ == () or (undef)
+ ||
+ (keys %$attrs # empty attrs or only 'safe' attrs
+ && List::Util::first { !$safe{$_} } keys %$attrs)
+ ) {
+ # no search, effectively just a clone
+ $rows = $self->get_cache;
+ }
+
my $new_attrs = { %{$our_attrs}, %{$attrs} };
# merge new attrs into inherited
Pass a literal chunk of SQL to be added to the conditional part of the
resultset query.
+CAVEAT: C<search_literal> is provided for Class::DBI compatibility and should
+only be used in that context. There are known problems using C<search_literal>
+in chained queries; it can result in bind values in the wrong order. See
+L<DBIx::Class::Manual::Cookbook/Searching> and
+L<DBIx::Class::Manual::FAQ/Searching> for searching techniques that do not
+require C<search_literal>.
+
=cut
sub search_literal {
return shift->related_resultset(shift)->search(@_);
}
+=head2 search_related_rs
+
+This method works exactly the same as search_related, except that
+it garauntees a restultset, even in list context.
+
+=cut
+
+sub search_related_rs {
+ return shift->related_resultset(shift)->search_rs(@_);
+}
+
=head2 cursor
=over 4
with to find the number of elements. If passed arguments, does a search
on the resultset and counts the results of that.
-Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
+Note: When using C<count> with C<group_by>, L<DBIx::Class> emulates C<GROUP BY>
using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
not support C<DISTINCT> with multiple columns. If you are using such a
database, you should only use columns from the main table in your C<group_by>
my $alias = $self->{attrs}{alias};
my $collapsed_cond = $self->{cond} ? $self->_collapse_cond($self->{cond}) : {};
+
+ # precendence must be given to passed values over values inherited from the cond,
+ # so the order here is important.
my %new = (
- %{ $self->_remove_alias($values, $alias) },
%{ $self->_remove_alias($collapsed_cond, $alias) },
+ %{ $self->_remove_alias($values, $alias) },
-source_handle => $self->_source_handle,
-result_source => $self->result_source, # DO NOT REMOVE THIS, REQUIRED
);
=item Arguments: \%vals
-=item Return Value: $object
+=item Return Value: a L<DBIx::Class::Row> $object
=back
$position++;
}
my ($b_key) = ( ref $b_element eq 'HASH' ) ? keys %{$b_element} : ($b_element);
+
if ($best_candidate->{score} == 0 || exists $seen_keys->{$b_key}) {
push( @{$a}, $b_element );
} else {
- $seen_keys->{$b_key} = 1; # don't merge the same key twice
my $a_best = $a->[$best_candidate->{position}];
# merge a_best and b_element together and replace original with merged
if (ref $a_best ne 'HASH') {
$a->[$best_candidate->{position}] = { $key => $self->_merge_attr($a_best->{$key}, $b_element->{$key}) };
}
}
+ $seen_keys->{$b_key} = 1; # don't merge the same key twice
}
return $a;
sub throw_exception {
my $self=shift;
- $self->_source_handle->schema->throw_exception(@_);
+ if (ref $self && $self->_source_handle->schema) {
+ $self->_source_handle->schema->throw_exception(@_)
+ } else {
+ croak(@_);
+ }
+
}
# XXX: FIXME: Attributes docs need clearing up
=over 4
Indicates additional columns to be selected from storage. Works the same as
-L<select> but adds columns to the selection.
+L</select> but adds columns to the selection.
=back
=over 4
-Indicates additional column names for those added via L<+select>.
+Indicates additional column names for those added via L</+select>.
=back
=back
-Indicates column names for object inflation. That is, c< as >
+Indicates column names for object inflation. That is, C<as>
indicates the name that the column can be accessed as via the
C<get_column> method (or via the object accessor, B<if one already
-exists>). It has nothing to do with the SQL code C< SELECT foo AS bar
->.
+exists>). It has nothing to do with the SQL code C<SELECT foo AS bar>.
The C<as> attribute is used in conjunction with C<select>,
usually when C<select> contains one or more function or stored
If you want to fetch related objects from other tables as well, see C<prefetch>
below.
+For more help on using joins with search, see L<DBIx::Class::Manual::Joining>.
+
=head2 prefetch
=over 4