From: Justin Hunter Date: Sat, 14 Mar 2009 13:55:55 +0000 (+0000) Subject: Merge 'trunk' into 'count_distinct' X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=458073b6c090dde311756e8aa22c8d78285bb016;hp=f4ca1906932c6127745d5b23524f61be24f4c2ee;p=dbsrgits%2FDBIx-Class-Historic.git Merge 'trunk' into 'count_distinct' created count_distinct branch --- diff --git a/Makefile.PL b/Makefile.PL index 9c1633a..8acdc1e 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -82,6 +82,18 @@ if ($Module::Install::AUTHOR) { 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 @@ -210,3 +222,4 @@ if ($Module::Install::AUTHOR) { ]; Meta->write; } + diff --git a/lib/DBIx/Class.pm b/lib/DBIx/Class.pm index b0612ae..bb73581 100644 --- a/lib/DBIx/Class.pm +++ b/lib/DBIx/Class.pm @@ -207,8 +207,6 @@ andyg: Andy Grundman ank: Andres Kievsky -arcanez: Justin Hunter - ash: Ash Berlin bert: Norbert Csongradi diff --git a/lib/DBIx/Class/Manual/FAQ.pod b/lib/DBIx/Class/Manual/FAQ.pod index 273397a..7d4505e 100644 --- a/lib/DBIx/Class/Manual/FAQ.pod +++ b/lib/DBIx/Class/Manual/FAQ.pod @@ -274,7 +274,7 @@ replaced with the following.) 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? @@ -353,6 +353,20 @@ to get a new, fresh copy of the row, just re-fetch the row from storage. L 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 and C attributes to your search, eg: + + ->search({}, { rows => 10, page => 1}); + +=item .. get a count of all rows even when paging? + +Call C on the paged resultset, it will return a L +object. Calling C on the pager will return the correct +total. + +C on the resultset will only return the total number in the page. + =back =head2 Inserting and updating data diff --git a/lib/DBIx/Class/Relationship/Accessor.pm b/lib/DBIx/Class/Relationship/Accessor.pm index 02f7db5..065cf69 100644 --- a/lib/DBIx/Class/Relationship/Accessor.pm +++ b/lib/DBIx/Class/Relationship/Accessor.pm @@ -31,17 +31,11 @@ sub add_relationship_accessor { $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; } diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index b5d8086..dd911ad 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -102,6 +102,21 @@ another. }); } +=head3 Resolving conditions and attributes + +When a resultset is chained from another resultset, conditions and +attributes with the same keys need resolving. + +L, L, L, L attributes are merged +into the existing ones from the original resultset. + +The L, L attribute, and any search conditions are +merged with an SQL C 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 @@ -313,11 +328,6 @@ sub search_rs { : 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} @@ -1133,11 +1143,11 @@ sub count { 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; @@ -1151,15 +1161,14 @@ sub _count { # Separated out so pager can get the full count } } - $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; @@ -1642,6 +1651,9 @@ sub _normalize_populate_args { Return Value a L object for the current resultset. Only makes sense for queries with a C attribute. +To get the full count of entries for a paged resultset, call +C on the L object. + =cut sub pager { @@ -2863,6 +2875,10 @@ on it. If L attribute is not specified it defualts to 10 rows per page. +When you have a paged resultset, L will only return the number +of rows in the page. To get the total, use the L and call +C on it. + =head2 rows =over 4 diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index 2c0b43f..cf7267d 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -483,6 +483,12 @@ Note that C expects an arrayref of arguments, but C does not. C wraps it's arguments in an arrayref before passing them to C. +=head3 Overloading + +C is a convenience method. It is equivalent to calling +$schema->clone->connection(@connectinfo). To write your own overloaded +version, overload L instead. + =cut sub connect { shift->clone->connection(@_) } @@ -760,6 +766,9 @@ Similar to L except sets the storage object and connection data in-place on the Schema class. You should probably be calling L to get a proper Schema object instead. +=head3 Overloading + +Overload C to change the behaviour of C. =cut diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index c27647c..4bfa2e8 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -95,9 +95,6 @@ sub _find_syntax { sub select { my ($self, $table, $fields, $where, $order, @rest) = @_; - local $self->{having_bind} = []; - local $self->{from_bind} = []; - if (ref $table eq 'SCALAR') { $table = $$table; } @@ -109,7 +106,8 @@ sub select { @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 .= @@ -121,7 +119,7 @@ sub select { ) : '' ; - return wantarray ? ($sql, @{$self->{from_bind}}, @where_bind, @{$self->{having_bind}}) : $sql; + return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql; } sub insert { @@ -269,10 +267,11 @@ sub _recurse_from { } 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 { diff --git a/t/39load_namespaces_rt41083.t b/t/39load_namespaces_rt41083.t index ba99fe5..7d8dc5c 100644 --- a/t/39load_namespaces_rt41083.t +++ b/t/39load_namespaces_rt41083.t @@ -6,7 +6,7 @@ use Test::More; use lib 't/lib'; -plan tests => 4; +plan tests => 6; sub _chk_warning { defined $_[0]? @@ -14,6 +14,11 @@ sub _chk_warning { 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 }; @@ -26,7 +31,9 @@ eval { ); }; 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 }; @@ -39,4 +46,6 @@ eval { ); }; 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; diff --git a/t/distinct_count.t b/t/distinct_count.t deleted file mode 100644 index b3f3446..0000000 --- a/t/distinct_count.t +++ /dev/null @@ -1,26 +0,0 @@ -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"); -