auto_provides;
+if ($Module::Install::AUTHOR) {
+ warn <<'EOW';
+******************************************************************************
+******************************************************************************
+*** ***
+*** AUTHOR MODE: all optional test dependencies converted to hard requires ***
+*** ***
+******************************************************************************
+******************************************************************************
+
+EOW
+}
auto_install;
# Have all prerequisites, check DBD::SQLite sanity
];
Meta->write;
}
+
ank: Andres Kievsky
-arcanez: Justin Hunter <justin.d.hunter@gmail.com>
-
ash: Ash Berlin <ash@cpan.org>
bert: Norbert Csongradi <bert@cpan.org>
Or, if you have quoting off:
- ->search({ 'YEAR(date_of_birth' => 1979 });
+ ->search({ 'YEAR(date_of_birth)' => 1979 });
=item .. find more help on constructing searches?
L<DBIx::Class::PK/discard_changes> does just that by re-fetching the row from storage
using the row's primary key.
+=item .. fetch my data a "page" at a time?
+
+Pass the C<rows> and C<page> attributes to your search, eg:
+
+ ->search({}, { rows => 10, page => 1});
+
+=item .. get a count of all rows even when paging?
+
+Call C<pager> on the paged resultset, it will return a L<Data::Page>
+object. Calling C<total_entries> on the pager will return the correct
+total.
+
+C<count> on the resultset will only return the total number in the page.
+
=back
=head2 Inserting and updating data
$rel_info->{cond}, $rel, $self
);
if ($rel_info->{attrs}->{undef_on_null_fk}){
- return unless ref($cond) eq 'HASH';
- return if grep { not defined } values %$cond;
+ return undef unless ref($cond) eq 'HASH';
+ return undef if grep { not defined $_ } values %$cond;
}
my $val = $self->find_related($rel, {}, {});
-
- # this really should have been:
- # return $val unless $val
- # however someone might already be relying on return() as in:
- # my @things = map { $_->might_have_acc } ($rs->all)
- # thus keeping the quirky behavior
- return unless defined $val;
+ return $val unless $val; # $val instead of undef so that null-objects can go through
return $self->{_relationship_data}{$rel} = $val;
}
});
}
+=head3 Resolving conditions and attributes
+
+When a resultset is chained from another resultset, conditions and
+attributes with the same keys need resolving.
+
+L</join>, L</prefetch>, L</+select>, L</+as> attributes are merged
+into the existing ones from the original resultset.
+
+The L</where>, L</having> attribute, and any search conditions are
+merged with an SQL C<AND> to the existing condition from the original
+resultset.
+
+All other attributes are overridden by any new ones supplied in the
+search attributes.
+
=head2 Multiple queries
Since a resultset just defines a query, you can do all sorts of
: undef
);
- foreach my $key (keys %$cond) {
- next unless my ($alias) = ($key =~ /^(\w+)\.\w+$/);
- push @{$new_attrs->{join}}, $alias unless grep(/${alias}/, @{$new_attrs->{join}}) or $alias eq 'me';
- }
-
if (defined $where) {
$new_attrs->{where} = (
defined $new_attrs->{where}
sub _count { # Separated out so pager can get the full count
my $self = shift;
- my $attrs = { %{$self->_resolved_attrs} };
+ my $select = { count => '*' };
- if (my $group_by = $attrs->{group_by}) {
+ my $attrs = { %{$self->_resolved_attrs} };
+ if (my $group_by = delete $attrs->{group_by}) {
delete $attrs->{having};
- delete $attrs->{order_by};
my @distinct = (ref $group_by ? @$group_by : ($group_by));
# todo: try CONCAT for multi-column pk
my @pk = $self->result_source->primary_columns;
}
}
- $attrs->{select} = $group_by;
- $attrs->{from} = [ { 'mesub' => (ref $self)->new($self->result_source, $attrs)->cursor->as_query } ];
+ $select = { count => { distinct => \@distinct } };
}
- $attrs->{select} = { count => '*' };
+ $attrs->{select} = $select;
$attrs->{as} = [qw/count/];
- # offset, order by, group by, where and page are not needed to count. record_filter is cdbi
- delete $attrs->{$_} for qw/rows offset order_by group_by where page pager record_filter/;
+ # offset, order by and page are not needed to count. record_filter is cdbi
+ delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
my $tmp_rs = (ref $self)->new($self->result_source, $attrs);
my ($count) = $tmp_rs->cursor->next;
Return Value a L<Data::Page> object for the current resultset. Only makes
sense for queries with a C<page> attribute.
+To get the full count of entries for a paged resultset, call
+C<total_entries> on the L<Data::Page> object.
+
=cut
sub pager {
If L<rows> attribute is not specified it defualts to 10 rows per page.
+When you have a paged resultset, L</count> will only return the number
+of rows in the page. To get the total, use the L</pager> and call
+C<total_entries> on it.
+
=head2 rows
=over 4
C<connect> does not. C<connect> wraps it's arguments in an arrayref
before passing them to C<connect_info>.
+=head3 Overloading
+
+C<connect> is a convenience method. It is equivalent to calling
+$schema->clone->connection(@connectinfo). To write your own overloaded
+version, overload L</connection> instead.
+
=cut
sub connect { shift->clone->connection(@_) }
data in-place on the Schema class. You should probably be calling
L</connect> to get a proper Schema object instead.
+=head3 Overloading
+
+Overload C<connection> to change the behaviour of C<connect>.
=cut
sub select {
my ($self, $table, $fields, $where, $order, @rest) = @_;
- local $self->{having_bind} = [];
- local $self->{from_bind} = [];
-
if (ref $table eq 'SCALAR') {
$table = $$table;
}
@rest = (-1) unless defined $rest[0];
die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
# and anyway, SQL::Abstract::Limit will cause a barf if we don't first
- my ($sql, @where_bind) = $self->SUPER::select(
+ local $self->{having_bind} = [];
+ my ($sql, @ret) = $self->SUPER::select(
$table, $self->_recurse_fields($fields), $where, $order, @rest
);
$sql .=
) :
''
;
- return wantarray ? ($sql, @{$self->{from_bind}}, @where_bind, @{$self->{having_bind}}) : $sql;
+ return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
}
sub insert {
}
sub _bind_to_sql {
- my ($self, $arr) = @_;
- my ($sql, @bind) = @{${$arr}};
- push (@{$self->{from_bind}}, @bind);
- return $sql;
+ my $self = shift;
+ my $arr = shift;
+ my $sql = shift @$$arr;
+ $sql =~ s/\?/$self->_quote((shift @$$arr)->[1])/eg;
+ return $sql
}
sub _make_as {
use lib 't/lib';
-plan tests => 4;
+plan tests => 6;
sub _chk_warning {
defined $_[0]?
1
}
+sub _chk_extra_sources_warning {
+ my $p = qr/already has a source, use register_extra_source for additional sources/;
+ defined $_[0]? $_[0] !~ /$p/ : 1;
+}
+
my $warnings;
eval {
local $SIG{__WARN__} = sub { $warnings .= shift };
);
};
ok(!$@) or diag $@;
-ok(_chk_warning($warnings), 'expected no complaint');
+ok(_chk_warning($warnings), 'expected no resultset complaint');
+ok(_chk_extra_sources_warning($warnings), 'expected no extra sources complaint');
+undef $warnings;
eval {
local $SIG{__WARN__} = sub { $warnings .= shift };
);
};
ok(!$@) or diag $@;
-ok(_chk_warning($warnings), 'expected no complaint') or diag $warnings;
+ok(_chk_warning($warnings), 'expected no resultset complaint') or diag $warnings;
+ok(_chk_extra_sources_warning($warnings), 'expected no extra sources complaint');
+undef $warnings;
+++ /dev/null
-use strict;
-use warnings;
-
-use Test::More;
-use lib qw(t/lib);
-use lib '/sporkrw/xfer/DBIx-Class/0.08/branches/count_distinct/lib';
-use DBICTest;
-
-my $schema = DBICTest->init_schema();
-
-eval "use DBD::SQLite";
-plan skip_all => 'needs DBD::SQLite for testing' if $@;
-plan tests => 4;
-
-cmp_ok($schema->resultset("Tag")->count({ tag => 'Blue' }),
- '==', 9, 'Count without DISTINCT ok');
-
-cmp_ok($schema->resultset("Tag")->count({ tag => [ 'Blue', 'Shiny' ] }, { group_by => 'tag' }),
- '==', 2, 'Count with single column group_by ok');
-
-cmp_ok($schema->resultset("Tag")->count({ tag => 'Blue' }, { group_by => [ qw/tag cd/ ]}),
- '==', 4, 'Count with multiple column group_by ok');
-
-cmp_ok($schema->resultset("Tag")->count({ tag => 'Blue' }, { distinct => 1 }),
- '==', 4, "Count with single column distinct ok");
-