[Bast-commits] r6219 - in DBIx-Class/0.08/trunk: . lib/DBIx/Class lib/DBIx/Class/Manual lib/DBIx/Class/Storage lib/DBIx/Class/Storage/DBI lib/DBIx/Class/Storage/DBI/Oracle t t/count t/resultset t/search

ribasushi at dev.catalyst.perl.org ribasushi at dev.catalyst.perl.org
Tue May 12 05:02:56 GMT 2009


Author: ribasushi
Date: 2009-05-12 05:02:56 +0000 (Tue, 12 May 2009)
New Revision: 6219

Added:
   DBIx-Class/0.08/trunk/t/count/count_distinct.t
   DBIx-Class/0.08/trunk/t/count/count_joined.t
   DBIx-Class/0.08/trunk/t/from_subquery.t
Removed:
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/MultiDistinctEmulation.pm
Modified:
   DBIx-Class/0.08/trunk/
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod
   DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/SQLite.pm
   DBIx-Class/0.08/trunk/t/03podcoverage.t
   DBIx-Class/0.08/trunk/t/47bind_attribute.t
   DBIx-Class/0.08/trunk/t/60core.t
   DBIx-Class/0.08/trunk/t/73oracle.t
   DBIx-Class/0.08/trunk/t/resultset/as_query.t
   DBIx-Class/0.08/trunk/t/search/subquery.t
Log:
 r5757 at Thesaurus (orig r5756):  arcanez | 2009-03-14 14:55:55 +0100
 created count_distinct branch
 r5758 at Thesaurus (orig r5757):  arcanez | 2009-03-14 15:33:03 +0100
  * change count with group_by (distinct) to use a subquery
  * rewrite of _bind_to_sql (uses placeholders and bindvars)
  * tests for count distinct
  * fixed tests for from subquery 
 
 r5760 at Thesaurus (orig r5759):  arcanez | 2009-03-16 16:48:28 +0100
 don't remove the where clause unless we're doing distinct, it needs to be there
 r5850 at Thesaurus (orig r5849):  arcanez | 2009-03-30 21:40:05 +0200
  * add more tests
  * remove old cruft
  * remove old note
 
 r6035 at Thesaurus (orig r6034):  ribasushi | 2009-04-30 09:10:36 +0200
 Add joined count test
 r6079 at Thesaurus (orig r6078):  arcanez | 2009-05-01 08:41:34 +0200
 cleanup/fix some broken tests
 r6097 at Thesaurus (orig r6096):  arcanez | 2009-05-01 19:37:04 +0200
 make sure merge bind
 test for aformentioned
 TODO count_joined test for a little while
 
 r6105 at Thesaurus (orig r6104):  arcanez | 2009-05-02 02:33:49 +0200
 remove hackish ways
 
 r6106 at Thesaurus (orig r6105):  arcanez | 2009-05-02 03:20:04 +0200
 more fixes to tests
 r6107 at Thesaurus (orig r6106):  arcanez | 2009-05-02 03:33:47 +0200
 remove DBIx::Class::Storage::DBI::MultiDistinctEmulation
 r6111 at Thesaurus (orig r6110):  ribasushi | 2009-05-03 02:00:19 +0200
 Failing test without immediate fixes go to branches, not to trunk
 r6114 at Thesaurus (orig r6113):  ribasushi | 2009-05-03 10:23:28 +0200
 Bump SQLA ependencies so parenthesis_significant is guaranteed to be there
 r6148 at Thesaurus (orig r6147):  ribasushi | 2009-05-06 17:40:31 +0200
 Add subquery/from test by michaelr (copied from subquery branch r5742)
 r6151 at Thesaurus (orig r6150):  ribasushi | 2009-05-06 17:56:07 +0200
 TODOify sqla-dependent tests
 r6152 at Thesaurus (orig r6151):  arcanez | 2009-05-06 18:33:58 +0200
 fix old test using new bind vars (no more interpolating)
 r6154 at Thesaurus (orig r6153):  ribasushi | 2009-05-07 00:56:40 +0200
 Rename internal function to clarify what it does
 r6171 at Thesaurus (orig r6170):  ribasushi | 2009-05-07 19:53:30 +0200
 Adjust tests for the IN fixes
 r6187 at Thesaurus (orig r6186):  ribasushi | 2009-05-08 23:11:43 +0200
 Final count tests
 r6188 at Thesaurus (orig r6187):  arcanez | 2009-05-09 03:50:12 +0200
 rewrite DISTINCT/COUNT(DISTINCT) Cookbook entries
 r6213 at Thesaurus (orig r6212):  arcanez | 2009-05-11 22:41:21 +0200
 warn/die based on { select => { distinct => { } } }
 r6214 at Thesaurus (orig r6213):  arcanez | 2009-05-11 23:21:11 +0200
 use carp instead of warn
 r6216 at Thesaurus (orig r6215):  arcanez | 2009-05-11 23:45:05 +0200
 make sure we get just a string
 r6217 at Thesaurus (orig r6216):  arcanez | 2009-05-11 23:52:11 +0200
 oops



Property changes on: DBIx-Class/0.08/trunk
___________________________________________________________________
Name: svn:mergeinfo
   - 
Name: svk:merge
   - 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5969
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_column_attr:10946
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:11142
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/column_attr:5074
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/fix-update-and-delete-as_query:6162
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multi_stuff:5565
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch:5699
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rt_bug_41083:5437
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subclassed_rsset:5930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase:5651
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_mssql:6125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/views:5585
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
   + 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5969
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_column_attr:10946
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:11142
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/column_attr:5074
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_distinct:6218
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/fix-update-and-delete-as_query:6162
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multi_stuff:5565
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch:5699
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rt_bug_41083:5437
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subclassed_rsset:5930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase:5651
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_mssql:6125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/views:5585
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod	2009-05-12 05:02:56 UTC (rev 6219)
@@ -237,30 +237,50 @@
 
 =head2 SELECT DISTINCT with multiple columns
 
-  my $rs = $schema->resultset('Foo')->search(
+  my $rs = $schema->resultset('Artist')->search(
     {},
     {
-      select => [
-        { distinct => [ $source->columns ] }
-      ],
-      as => [ $source->columns ] # remember 'as' is not the same as SQL AS :-)
+      columns => [ qw/artistid name rank/ ],
+      distinct => 1
+    } 
+  );
+
+  my $rs = $schema->resultset('Artist')->search(
+    {},
+    {
+      columns => [ qw/artistid name rank/ ],
+      group_by => [ qw/artistid name rank/ ],
     }
   );
 
+  # Equivalent SQL:
+  # SELECT me.artistid, me.name, me.rank
+  # FROM artist me
+  # GROUP BY artistid, name, rank
+
 =head2 SELECT COUNT(DISTINCT colname)
 
-  my $rs = $schema->resultset('Foo')->search(
+  my $rs = $schema->resultset('Artist')->search(
     {},
     {
-      select => [
-        { count => { distinct => 'colname' } }
-      ],
-      as => [ 'count' ]
+      columns => [ qw/name/ ],
+      distinct => 1
     }
   );
 
-  my $count = $rs->next->get_column('count');
+  my $rs = $schema->resultset('Artist')->search(
+    {},
+    {
+      columns => [ qw/name/ ],
+      group_by => [ qw/name/ ],
+    }
+  );
 
+  my $count = $rs->count;
+
+  # Equivalent SQL:
+  # SELECT COUNT( DISTINCT( me.name ) ) FROM artist me 
+
 =head2 Grouping results
 
 L<DBIx::Class> supports C<GROUP BY> as follows:

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm	2009-05-12 05:02:56 UTC (rev 6219)
@@ -307,7 +307,7 @@
   my $new_attrs = { %{$our_attrs}, %{$attrs} };
 
   # merge new attrs into inherited
-  foreach my $key (qw/join prefetch +select +as/) {
+  foreach my $key (qw/join prefetch +select +as bind/) {
     next unless exists $attrs->{$key};
     $new_attrs->{$key} = $self->_merge_attr($our_attrs->{$key}, $attrs->{$key});
   }
@@ -1148,12 +1148,6 @@
 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>
-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>
-clause.
-
 =cut
 
 sub count {
@@ -1174,32 +1168,21 @@
 
 sub _count { # Separated out so pager can get the full count
   my $self = shift;
-  my $select = { count => '*' };
-
   my $attrs = { %{$self->_resolved_attrs} };
-  if (my $group_by = delete $attrs->{group_by}) {
-    delete $attrs->{having};
-    my @distinct = (ref $group_by ?  @$group_by : ($group_by));
-    # todo: try CONCAT for multi-column pk
-    my @pk = $self->result_source->primary_columns;
-    if (@pk == 1) {
-      my $alias = $attrs->{alias};
-      foreach my $column (@distinct) {
-        if ($column =~ qr/^(?:\Q${alias}.\E)?$pk[0]$/) {
-          @distinct = ($column);
-          last;
-        }
-      }
-    }
 
-    $select = { count => { distinct => \@distinct } };
+  if (my $group_by = $attrs->{group_by}) {
+    delete $attrs->{order_by};
+
+    $attrs->{select} = $group_by; 
+    $attrs->{from} = [ { 'mesub' => (ref $self)->new($self->result_source, $attrs)->cursor->as_query } ];
+    delete $attrs->{where};
   }
 
-  $attrs->{select} = $select;
+  $attrs->{select} = { count => '*' };
   $attrs->{as} = [qw/count/];
 
-  # 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/;
+  # 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 page pager record_filter/;
 
   my $tmp_rs = (ref $self)->new($self->result_source, $attrs);
   my ($count) = $tmp_rs->cursor->next;

Deleted: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/MultiDistinctEmulation.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/MultiDistinctEmulation.pm	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/MultiDistinctEmulation.pm	2009-05-12 05:02:56 UTC (rev 6219)
@@ -1,51 +0,0 @@
-package DBIx::Class::Storage::DBI::MultiDistinctEmulation;
-
-use strict;
-use warnings;
-
-use base qw/DBIx::Class::Storage::DBI/;
-
-sub _select {
-  my ($self, $ident, $select, $condition, $attrs) = @_;
-
-  # hack to make count distincts with multiple columns work in SQLite and Oracle
-  if (ref $select eq 'ARRAY') { 
-      @{$select} = map {$self->replace_distincts($_)} @{$select};
-  } else { 
-      $select = $self->replace_distincts($select);
-  }
-
-  return $self->next::method($ident, $select, $condition, $attrs);
-}
-
-sub replace_distincts {
-    my ($self, $select) = @_;
-
-    $select->{count}->{distinct} = join("||", @{$select->{count}->{distinct}}) 
-	if (ref $select eq 'HASH' && $select->{count} && ref $select->{count} eq 'HASH' && 
-	    $select->{count}->{distinct} && ref $select->{count}->{distinct} eq 'ARRAY');
-
-    return $select;
-}
-
-1;
-
-=head1 NAME 
-
-DBIx::Class::Storage::DBI::MultiDistinctEmulation - Some databases can't handle count distincts with multiple cols. They should use base on this.
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-This class allows count distincts with multiple columns for retarded databases (Oracle and SQLite)
-
-=head1 AUTHORS
-
-Luke Saunders <luke.saunders at gmail.com>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm	2009-05-12 05:02:56 UTC (rev 6219)
@@ -26,7 +26,7 @@
 
 use Carp::Clan qw/^DBIx::Class/;
 
-use base qw/DBIx::Class::Storage::DBI::MultiDistinctEmulation/;
+use base qw/DBIx::Class::Storage::DBI/;
 
 # __PACKAGE__->load_components(qw/PK::Auto/);
 

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/SQLite.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/SQLite.pm	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI/SQLite.pm	2009-05-12 05:02:56 UTC (rev 6219)
@@ -6,7 +6,7 @@
 use File::Copy;
 use File::Spec;
 
-use base qw/DBIx::Class::Storage::DBI::MultiDistinctEmulation/;
+use base qw/DBIx::Class::Storage::DBI/;
 
 sub _dbh_last_insert_id {
   my ($self, $dbh, $source, $col) = @_;

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm	2009-05-12 05:02:56 UTC (rev 6219)
@@ -37,6 +37,7 @@
   DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
 
 use base qw/SQL::Abstract::Limit/;
+use Carp::Clan qw/^DBIx::Class/;
 
 sub new {
   my $self = shift->SUPER::new(@_);
@@ -147,6 +148,9 @@
 
 sub select {
   my ($self, $table, $fields, $where, $order, @rest) = @_;
+  local $self->{having_bind} = [];
+  local $self->{from_bind} = [];
+
   if (ref $table eq 'SCALAR') {
     $table = $$table;
   }
@@ -158,8 +162,7 @@
   @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
-  local $self->{having_bind} = [];
-  my ($sql, @ret) = $self->SUPER::select(
+  my ($sql, @where_bind) = $self->SUPER::select(
     $table, $self->_recurse_fields($fields), $where, $order, @rest
   );
   $sql .= 
@@ -171,7 +174,7 @@
     ) :
     ''
   ;
-  return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
+  return wantarray ? ($sql, @{$self->{from_bind}}, @where_bind, @{$self->{having_bind}}) : $sql;
 }
 
 sub insert {
@@ -219,13 +222,30 @@
       } @$fields);
   } elsif ($ref eq 'HASH') {
     foreach my $func (keys %$fields) {
+      if ($func eq 'distinct') {
+        my $_fields = $fields->{$func};
+        if (ref $_fields eq 'ARRAY' && @{$_fields} > 1) {
+          die "Unsupported syntax, please use " . 
+              "{ group_by => [ qw/" . (join ' ', @$_fields) . "/ ] }" .
+              " or " .
+              "{ select => [ qw/" . (join ' ', @$_fields) . "/ ], distinct => 1 }";
+        }
+        else {
+          $_fields = @{$_fields}[0] if ref $_fields eq 'ARRAY';
+          carp "This syntax will be deprecated in 09, please use " . 
+               "{ group_by => '${_fields}' }" . 
+               " or " .
+               "{ select => '${_fields}', distinct => 1 }";
+        }
+      }
+      
       return $self->_sqlcase($func)
         .'( '.$self->_recurse_fields($fields->{$func}).' )';
     }
   }
   # Is the second check absolutely necessary?
   elsif ( $ref eq 'REF' and ref($$fields) eq 'ARRAY' ) {
-    return $self->_bind_to_sql( $fields );
+    return $self->_fold_sqlbind( $fields );
   }
   else {
     Carp::croak($ref . qq{ unexpected in _recurse_fields()})
@@ -318,19 +338,18 @@
   return join('', @sqlf);
 }
 
-sub _bind_to_sql {
-  my $self = shift;
-  my $arr  = shift;
-  my $sql = shift @$$arr;
-  $sql =~ s/\?/$self->_quote((shift @$$arr)->[1])/eg;
-  return $sql
+sub _fold_sqlbind {
+  my ($self, $sqlbind) = @_;
+  my $sql = shift @$$sqlbind;
+  push @{$self->{from_bind}}, @$$sqlbind;
+  return $sql;
 }
 
 sub _make_as {
   my ($self, $from) = @_;
-  return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ 
-                        : ref $_ eq 'REF'    ? $self->_bind_to_sql($_) 
-                        : $self->_quote($_)) 
+  return join(' ', map { (ref $_ eq 'SCALAR' ? $$_
+                        : ref $_ eq 'REF'    ? $self->_fold_sqlbind($_)
+                        : $self->_quote($_))
                        } reverse each %{$self->_skip_options($from)});
 }
 

Modified: DBIx-Class/0.08/trunk/t/03podcoverage.t
===================================================================
--- DBIx-Class/0.08/trunk/t/03podcoverage.t	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/t/03podcoverage.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -99,7 +99,6 @@
     'DBIx::Class::Storage::DBI'                         => { skip => 1 },
     'DBIx::Class::Storage::DBI::DB2'                    => { skip => 1 },
     'DBIx::Class::Storage::DBI::MSSQL'                  => { skip => 1 },
-    'DBIx::Class::Storage::DBI::MultiDistinctEmulation' => { skip => 1 },
     'DBIx::Class::Storage::DBI::ODBC400'                => { skip => 1 },
     'DBIx::Class::Storage::DBI::ODBC::DB2_400_SQL'      => { skip => 1 },
     'DBIx::Class::Storage::DBI::Oracle'                 => { skip => 1 },

Modified: DBIx-Class/0.08/trunk/t/47bind_attribute.t
===================================================================
--- DBIx-Class/0.08/trunk/t/47bind_attribute.t	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/t/47bind_attribute.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -3,19 +3,19 @@
 
 use Test::More;
 use lib qw(t/lib);
-use DBICTest;
+use DBIC::SqlMakerTest;
 
+use_ok('DBICTest');
+
 my $schema = DBICTest->init_schema;
 
 BEGIN {
     eval "use DBD::SQLite";
     plan $@
         ? ( skip_all => 'needs DBD::SQLite for testing' )
-        : ( tests => 7 );
+        : ( tests => 9 );
 }
 
-### $schema->storage->debug(1);
-
 my $where_bind = {
     where => \'name like ?',
     bind  => [ 'Cat%' ],
@@ -55,10 +55,10 @@
 $new_source->source_name('Complex');
 
 $new_source->name(\<<'');
-( select a.*, cd.cdid as cdid, cd.title as title, cd.year as year 
-  from artist a
-  join cd on cd.artist=a.artistid
-  where cd.year=?)
+( SELECT a.*, cd.cdid AS cdid, cd.title AS title, cd.year AS year 
+  FROM artist a
+  JOIN cd ON cd.artist = a.artistid
+  WHERE cd.year = ?)
 
 $schema->register_extra_source('Complex' => $new_source);
 
@@ -72,11 +72,22 @@
     ->search({ 'artistid' => 1 });
 is ( $rs->count, 1, '...cookbook (bind first) + chained search' );
 
+{
+  $rs = $schema->resultset('Complex')->search({}, { bind => [ 1999 ] })->search({}, { where => \"title LIKE ?", bind => [ 'Spoon%' ] });
+  my ($sql, @bind) = @${$rs->as_query};
+  is_same_sql_bind(
+    $sql, \@bind,
+    "(SELECT me.artistid, me.name, me.rank, me.charfield FROM (SELECT a.*, cd.cdid AS cdid, cd.title AS title, cd.year AS year FROM artist a JOIN cd ON cd.artist = a.artistid WHERE cd.year = ?) WHERE title LIKE ?)",
+    [
+      [ '!!dummy' => '1999' ], 
+      [ '!!dummy' => 'Spoon%' ]
+    ],
+    'got correct SQL'
+);
+
+}
+
 TODO: {
-    # not sure what causes an uninit warning here, please remove when the TODO starts to pass,
-    # so the real reason for the warning can be found and fixed
-    local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /uninitialized/ };
-
     local $TODO = 'bind args order needs fixing (semifor)';
     $rs = $schema->resultset('Complex')->search({}, { bind => [ 1999 ] })
         ->search({ 'artistid' => 1 }, {

Modified: DBIx-Class/0.08/trunk/t/60core.t
===================================================================
--- DBIx-Class/0.08/trunk/t/60core.t	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/t/60core.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -8,7 +8,7 @@
 
 my $schema = DBICTest->init_schema();
 
-plan tests => 95;
+plan tests => 96;
 
 eval { require DateTime::Format::MySQL };
 my $NO_DTFM = $@ ? 1 : 0;
@@ -28,7 +28,7 @@
 
 my @art = $schema->resultset("Artist")->search({ }, { order_by => 'name DESC'});
 
-cmp_ok(@art, '==', 3, "Three artists returned");
+is(@art, 3, "Three artists returned");
 
 my $art = $art[0];
 
@@ -39,7 +39,7 @@
 is($art->name, 'We Are In Rehab', "Accessor update ok");
 
 my %dirty = $art->get_dirty_columns();
-cmp_ok(scalar(keys(%dirty)), '==', 1, '1 dirty column');
+is(scalar(keys(%dirty)), 1, '1 dirty column');
 ok(grep($_ eq 'name', keys(%dirty)), 'name is dirty');
 
 is($art->get_column("name"), 'We Are In Rehab', 'And via get_column');
@@ -47,7 +47,7 @@
 ok($art->update, 'Update run');
 
 my %not_dirty = $art->get_dirty_columns();
-cmp_ok(scalar(keys(%not_dirty)), '==', 0, 'Nothing is dirty');
+is(scalar(keys(%not_dirty)), 0, 'Nothing is dirty');
 
 eval {
   my $ret = $art->make_column_dirty('name2');
@@ -55,7 +55,7 @@
 ok(defined($@), 'Failed to make non-existent column dirty');
 $art->make_column_dirty('name');
 my %fake_dirty = $art->get_dirty_columns();
-cmp_ok(scalar(keys(%fake_dirty)), '==', 1, '1 fake dirty column');
+is(scalar(keys(%fake_dirty)), 1, '1 fake dirty column');
 ok(grep($_ eq 'name', keys(%fake_dirty)), 'name is fake dirty');
 
 my $record_jp = $schema->resultset("Artist")->search(undef, { join => 'cds' })->search(undef, { prefetch => 'cds' })->next;
@@ -68,15 +68,15 @@
 
 @art = $schema->resultset("Artist")->search({ name => 'We Are In Rehab' });
 
-cmp_ok(@art, '==', 1, "Changed artist returned by search");
+is(@art, 1, "Changed artist returned by search");
 
-cmp_ok($art[0]->artistid, '==', 3,'Correct artist too');
+is($art[0]->artistid, 3,'Correct artist too');
 
 lives_ok (sub { $art->delete }, 'Cascading delete on Ordered has_many works' );  # real test in ordered.t
 
 @art = $schema->resultset("Artist")->search({ });
 
-cmp_ok(@art, '==', 2, 'And then there were two');
+is(@art, 2, 'And then there were two');
 
 ok(!$art->in_storage, "It knows it's dead");
 
@@ -90,15 +90,15 @@
 
 @art = $schema->resultset("Artist")->search({ });
 
-cmp_ok(@art, '==', 3, 'And now there are three again');
+is(@art, 3, 'And now there are three again');
 
 my $new = $schema->resultset("Artist")->create({ artistid => 4 });
 
-cmp_ok($new->artistid, '==', 4, 'Create produced record ok');
+is($new->artistid, 4, 'Create produced record ok');
 
 @art = $schema->resultset("Artist")->search({ });
 
-cmp_ok(@art, '==', 4, "Oh my god! There's four of them!");
+is(@art, 4, "Oh my god! There's four of them!");
 
 $new->set_column('name' => 'Man With A Fork');
 
@@ -152,7 +152,7 @@
 my $cd = $schema->resultset("CD")->find(1);
 my %cols = $cd->get_columns;
 
-cmp_ok(keys %cols, '==', 6, 'get_columns number of columns ok');
+is(keys %cols, 6, 'get_columns number of columns ok');
 
 is($cols{title}, 'Spoonful of bees', 'get_columns values ok');
 
@@ -235,31 +235,40 @@
 my( $or_rs ) = $schema->resultset("CD")->search_rs($search, { join => 'tags',
                                                   order_by => 'cdid' });
 
-cmp_ok($or_rs->count, '==', 5, 'Search with OR ok');
+is($or_rs->count, 5, 'Search with OR ok');
 
 my $distinct_rs = $schema->resultset("CD")->search($search, { join => 'tags', distinct => 1 });
-cmp_ok($distinct_rs->all, '==', 4, 'DISTINCT search with OR ok');
+is($distinct_rs->all, 4, 'DISTINCT search with OR ok');
 
 SKIP: {
   skip "SQLite < 3.2.6 doesn't understand COUNT(DISTINCT())", 2
     if $is_broken_sqlite;
 
-  my $tcount = $schema->resultset("Track")->search(
+  my $tcount = $schema->resultset('Track')->search(
     {},
-    {       
-       select => {count => {distinct => ['position', 'title']}},
-	   as => ['count']
+    {
+      select => [ qw/position title/ ],
+      distinct => 1,
     }
   );
-  cmp_ok($tcount->next->get_column('count'), '==', 13, 'multiple column COUNT DISTINCT ok');
+  is($tcount->count, 13, 'multiple column COUNT DISTINCT ok');
 
-  $tcount = $schema->resultset("Track")->search(
+  $tcount = $schema->resultset('Track')->search(
     {},
-    {       
-       columns => {count => {count => {distinct => ['position', 'title']}}},
+    {
+      columns => [ qw/position title/ ],
+      distinct => 1,
     }
   );
-  cmp_ok($tcount->next->get_column('count'), '==', 13, 'multiple column COUNT DISTINCT using column syntax ok');
+  is($tcount->count, 13, 'multiple column COUNT DISTINCT ok');
+
+  $tcount = $schema->resultset('Track')->search(
+    {},
+    {
+       group_by => [ qw/position title/ ]
+    }
+  );
+  is($tcount->count, 13, 'multiple column COUNT DISTINCT using column syntax ok');  
 }
 
 my $tag_rs = $schema->resultset('Tag')->search(
@@ -267,17 +276,17 @@
 
 my $rel_rs = $tag_rs->search_related('cd');
 
-cmp_ok($rel_rs->count, '==', 5, 'Related search ok');
+is($rel_rs->count, 5, 'Related search ok');
 
-cmp_ok($or_rs->next->cdid, '==', $rel_rs->next->cdid, 'Related object ok');
+is($or_rs->next->cdid, $rel_rs->next->cdid, 'Related object ok');
 $or_rs->reset;
 $rel_rs->reset;
 
 my $tag = $schema->resultset('Tag')->search(
                [ { 'me.tag' => 'Blue' } ], { cols=>[qw/tagid/] } )->next;
 
-cmp_ok($tag->has_column_loaded('tagid'), '==', 1, 'Has tagid loaded');
-cmp_ok($tag->has_column_loaded('tag'), '==', 0, 'Has not tag  loaded');
+ok($tag->has_column_loaded('tagid'), 'Has tagid loaded');
+ok(!$tag->has_column_loaded('tag'), 'Has not tag loaded');
 
 ok($schema->storage(), 'Storage available');
 
@@ -309,7 +318,7 @@
   ok($schema->source('SourceNameArtists'), 'SourceNameArtists result source exists');
 
   my @artsn = $schema->resultset('SourceNameArtists')->search({}, { order_by => 'name DESC' });
-  cmp_ok(@artsn, '==', 4, "Four artists returned");
+  is(@artsn, 4, "Four artists returned");
   
   # make sure subclasses that don't set source_name are ok
   ok($schema->source('ArtistSubclass'), 'ArtistSubclass exists');
@@ -323,8 +332,8 @@
 {
   my $art_del = $schema->resultset("Artist")->find({ artistid => 1 });
   lives_ok (sub { $art_del->delete }, 'Cascading delete on Ordered has_many works' );  # real test in ordered.t
-  cmp_ok( $schema->resultset("CD")->search({artist => 1}), '==', 0, 'Cascading through has_many top level.');
-  cmp_ok( $schema->resultset("CD_to_Producer")->search({cd => 1}), '==', 0, 'Cascading through has_many children.');
+  is( $schema->resultset("CD")->search({artist => 1}), 0, 'Cascading through has_many top level.');
+  is( $schema->resultset("CD_to_Producer")->search({cd => 1}), 0, 'Cascading through has_many children.');
 }
 
 # test column_info

Modified: DBIx-Class/0.08/trunk/t/73oracle.t
===================================================================
--- DBIx-Class/0.08/trunk/t/73oracle.t	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/t/73oracle.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -39,7 +39,7 @@
   ' as well as following sequences: \'pkid1_seq\', \'pkid2_seq\' and \'nonpkid_seq\''
   unless ($dsn && $user && $pass);
 
-plan tests => 24;
+plan tests => 26;
 
 DBICTest::Schema->load_classes('ArtistFQN');
 my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
@@ -106,16 +106,33 @@
 
 # check count distinct with multiple columns
 my $other_track = $schema->resultset('Track')->create({ trackid => 2, cd => 1, position => 1, title => 'Track2' });
+
 my $tcount = $schema->resultset('Track')->search(
-    {},
-    {
-        select => [{count => {distinct => ['position', 'title']}}],
-        as => ['count']
-    }
-  );
+  {},
+  {
+    select => [ qw/position title/ ],
+    distinct => 1,
+  }
+);
+is($tcount->count, 2, 'multiple column COUNT DISTINCT ok');
 
-is($tcount->next->get_column('count'), 2, "multiple column select distinct ok");
+$tcount = $schema->resultset('Track')->search(
+  {},
+  {
+    columns => [ qw/position title/ ],
+    distinct => 1,
+  }
+);
+is($tcount->count, 2, 'multiple column COUNT DISTINCT ok');
 
+$tcount = $schema->resultset('Track')->search(
+  {},
+  { 
+     group_by => [ qw/position title/ ]
+  }
+);
+is($tcount->count, 2, 'multiple column COUNT DISTINCT using column syntax ok');
+
 # test LIMIT support
 for (1..6) {
     $schema->resultset('Artist')->create({ name => 'Artist ' . $_ });

Added: DBIx-Class/0.08/trunk/t/count/count_distinct.t
===================================================================
--- DBIx-Class/0.08/trunk/t/count/count_distinct.t	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/count/count_distinct.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -0,0 +1,82 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use Test::Exception;
+
+use lib qw(t/lib);
+
+use DBICTest;
+use DBIC::SqlMakerTest;
+
+my $schema = DBICTest->init_schema();
+
+eval "use DBD::SQLite";
+plan skip_all => 'needs DBD::SQLite for testing' if $@;
+plan tests => 18;
+
+# The tag Blue is assigned to cds 1 2 3 and 5
+# The tag Cheesy is assigned to cds 2 4 and 5
+#
+# This combination should make some interesting group_by's
+#
+my $rs;
+my $in_rs = $schema->resultset('Tag')->search({ tag => [ 'Blue', 'Cheesy' ] });
+
+$rs = $schema->resultset('Tag')->search({ tag => 'Blue' });
+is($rs->count, 4, 'Count without DISTINCT');
+
+$rs = $schema->resultset('Tag')->search({ tag => [ 'Blue', 'Cheesy' ] }, { group_by => 'tag' });
+is($rs->count, 2, 'Count with single column group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => [ 'Blue', 'Cheesy' ] }, { group_by => 'cd' });
+is($rs->count, 5, 'Count with another single column group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => 'Blue' }, { group_by => [ qw/tag cd/ ]});
+is($rs->count, 4, 'Count with multiple column group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => 'Blue' }, { distinct => 1 });
+is($rs->count, 4, 'Count with single column distinct');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->get_column('tag')->as_query } });
+is($rs->count, 7, 'Count with IN subquery');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->get_column('tag')->as_query } }, { group_by => 'tag' });
+is($rs->count, 2, 'Count with IN subquery with outside group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->get_column('tag')->as_query } }, { distinct => 1 });
+is($rs->count, 7, 'Count with IN subquery with outside distinct');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->get_column('tag')->as_query } }, { distinct => 1, select => 'tag' }), 
+is($rs->count, 2, 'Count with IN subquery with outside distinct on a single column');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->search({}, { group_by => 'tag' })->get_column('tag')->as_query } });
+is($rs->count, 7, 'Count with IN subquery with single group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->search({}, { group_by => 'cd' })->get_column('tag')->as_query } });
+is($rs->count, 7, 'Count with IN subquery with another single group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => { -in => $in_rs->search({}, { group_by => [ qw/tag cd/ ] })->get_column('tag')->as_query } });
+is($rs->count, 7, 'Count with IN subquery with multiple group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => \"= 'Blue'" });
+is($rs->count, 4, 'Count without DISTINCT, using literal SQL');
+
+$rs = $schema->resultset('Tag')->search({ tag => \" IN ('Blue', 'Cheesy')" }, { group_by => 'tag' });
+is($rs->count, 2, 'Count with literal SQL and single group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => \" IN ('Blue', 'Cheesy')" }, { group_by => 'cd' });
+is($rs->count, 5, 'Count with literal SQL and another single group_by');
+
+$rs = $schema->resultset('Tag')->search({ tag => \" IN ('Blue', 'Cheesy')" }, { group_by => [ qw/tag cd/ ] });
+is($rs->count, 7, 'Count with literal SQL and multiple group_by');
+
+my @warnings;
+{
+  local $SIG{__WARN__} = sub { push @warnings, shift };
+  my $row = $schema->resultset('Tag')->search({}, { select => { distinct => 'tag' } })->first;
+}
+
+is(@warnings, 1, 'expecteing warn');
+
+dies_ok(sub { my $row = $schema->resultset('Tag')->search({}, { select => { distinct => [qw/tag cd/] } })->first }, 'expecting to die');


Property changes on: DBIx-Class/0.08/trunk/t/count/count_distinct.t
___________________________________________________________________
Name: svn:mergeinfo
   + 

Added: DBIx-Class/0.08/trunk/t/count/count_joined.t
===================================================================
--- DBIx-Class/0.08/trunk/t/count/count_joined.t	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/count/count_joined.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use lib qw(t/lib);
+
+use DBICTest;
+
+plan tests => 1;
+
+my $schema = DBICTest->init_schema();
+
+TODO: {
+  local $TODO = 'Needs -paren fixes in SQLA before it can work';
+  my $cds = $schema->resultset("CD")->search({ cdid => 1 }, { join => { cd_to_producer => 'producer' } });
+  is($cds->count, 1, "extra joins do not explode single entity count");
+}

Added: DBIx-Class/0.08/trunk/t/from_subquery.t
===================================================================
--- DBIx-Class/0.08/trunk/t/from_subquery.t	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/from_subquery.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -0,0 +1,192 @@
+use strict;
+use warnings FATAL => 'all';
+
+use Test::More;
+
+BEGIN {
+    eval "use SQL::Abstract 1.49";
+    plan $@
+        ? ( skip_all => "Needs SQLA 1.49+" )
+        : ( tests => 8 );
+}
+
+use lib qw(t/lib);
+use DBICTest;
+use DBIC::SqlMakerTest;
+
+my $schema = DBICTest->init_schema();
+my $art_rs = $schema->resultset('Artist');
+my $cdrs = $schema->resultset('CD');
+
+{
+  my $cdrs2 = $cdrs->search({
+    artist_id => { 'in' => $art_rs->search({}, { rows => 1 })->get_column( 'id' )->as_query },
+  });
+
+  my $arr = $cdrs2->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE artist_id IN ( SELECT id FROM artist me LIMIT 1 ))",
+    [],
+  );
+}
+
+{
+  my $rs = $art_rs->search(
+    {},
+    {
+      'select' => [
+        $cdrs->search({}, { rows => 1 })->get_column('id')->as_query,
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT (SELECT id FROM cd me LIMIT 1) FROM artist me)",
+    [],
+  );
+}
+
+{
+  my $rs = $art_rs->search(
+    {},
+    {
+      '+select' => [
+        $cdrs->search({}, { rows => 1 })->get_column('id')->as_query,
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT me.artistid, me.name, me.rank, me.charfield, (SELECT id FROM cd me LIMIT 1) FROM artist me)",
+    [],
+  );
+}
+
+# simple from
+{
+  my $rs = $cdrs->search(
+    {},
+    {
+      alias => 'cd2',
+      from => [
+        { cd2 => $cdrs->search({ id => { '>' => 20 } })->as_query },
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE ( id > ? ) ) cd2)",
+    [
+      [ 'id', 20 ]
+    ],
+  );
+}
+
+# nested from
+{
+  my $art_rs2 = $schema->resultset('Artist')->search({}, 
+  {
+    from => [ { 'me' => 'artist' }, 
+      [ { 'cds' => $cdrs->search({},{ 'select' => [\'me.artist as cds_artist' ]})->as_query },
+      { 'me.artistid' => 'cds_artist' } ] ]
+  });
+
+  my $arr = $art_rs2->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me JOIN (SELECT me.artist as cds_artist FROM cd me) cds ON me.artistid = cds_artist)",
+    []
+  );
+
+
+}
+
+# nested subquery in from
+{
+  my $rs = $cdrs->search(
+    {},
+    {
+      alias => 'cd2',
+      from => [
+        { cd2 => $cdrs->search(
+            { id => { '>' => 20 } }, 
+            { 
+                alias => 'cd3',
+                from => [ 
+                { cd3 => $cdrs->search( { id => { '<' => 40 } } )->as_query }
+                ],
+            }, )->as_query },
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track 
+      FROM 
+        (SELECT cd3.cdid,cd3.artist,cd3.title,cd3.year,cd3.genreid,cd3.single_track 
+          FROM 
+            (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track 
+              FROM cd me WHERE ( id < ? ) ) cd3
+          WHERE ( id > ? ) ) cd2)",
+    [
+      [ 'id', 40 ], 
+      [ 'id', 20 ]
+    ],
+  );
+
+}
+
+{
+  my $rs = $cdrs->search({
+    year => {
+      '=' => $cdrs->search(
+        { artistid => { '=' => \'me.artistid' } },
+        { alias => 'inner' }
+      )->get_column('year')->max_rs->as_query,
+    },
+  });
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE year = (SELECT MAX(inner.year) FROM cd inner WHERE artistid = me.artistid))",
+    [],
+  );
+}
+
+{
+  my $rs = $cdrs->search(
+    {},
+    {
+      alias => 'cd2',
+      from => [
+        { cd2 => $cdrs->search({ title => 'Thriller' })->as_query },
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE ( title = ? ) ) cd2)",
+    [ [ 'title', 'Thriller' ] ],
+  );
+}
+
+__END__

Modified: DBIx-Class/0.08/trunk/t/resultset/as_query.t
===================================================================
--- DBIx-Class/0.08/trunk/t/resultset/as_query.t	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/t/resultset/as_query.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -7,7 +7,7 @@
 
 use Test::More;
 
-plan ( tests => 4 );
+plan ( tests => 5 );
 
 use lib qw(t/lib);
 use DBICTest;
@@ -65,3 +65,12 @@
     [ [ rank => 2 ], [ name => 'Billy Joel' ] ],
   );
 }
+
+{
+  my $rs = $schema->resultset("CD")->search(
+    { 'artist.name' => 'Caterwauler McCrae' },
+    { join => [qw/artist/]}
+  );
+  my $subsel_rs = $schema->resultset("CD")->search( { cdid => { IN => $rs->get_column('cdid')->as_query } } );
+  is($subsel_rs->count, $rs->count, 'Subselect on PK got the same row count');
+}

Modified: DBIx-Class/0.08/trunk/t/search/subquery.t
===================================================================
--- DBIx-Class/0.08/trunk/t/search/subquery.t	2009-05-12 05:02:33 UTC (rev 6218)
+++ DBIx-Class/0.08/trunk/t/search/subquery.t	2009-05-12 05:02:56 UTC (rev 6219)
@@ -7,7 +7,7 @@
 
 use Test::More;
 
-plan ( tests => 7 );
+plan ( tests => 8 );
 
 use lib qw(t/lib);
 use DBICTest;
@@ -85,8 +85,10 @@
   my ($query, @bind) = @{$$arr};
   is_same_sql_bind(
     $query, \@bind,
-    "( SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE id > 20) cd2 )",
-    [],
+    "( SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE id > ?) cd2 )",
+    [
+      [ 'id', 20 ]
+    ],
   );
 }
 
@@ -137,10 +139,13 @@
         (SELECT cd3.cdid,cd3.artist,cd3.title,cd3.year,cd3.genreid,cd3.single_track 
           FROM 
             (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track 
-              FROM cd me WHERE id < 40) cd3
-          WHERE id > 20) cd2
+              FROM cd me WHERE id < ?) cd3
+          WHERE id > ?) cd2
     )",
-    [],
+    [
+      [ 'id', 40 ], 
+      [ 'id', 20 ]
+    ],
   );
 
 }
@@ -163,4 +168,28 @@
   );
 }
 
+{
+  my $rs = $cdrs->search(
+    {},
+    {
+      alias => 'cd2',
+      from => [
+        { cd2 => $cdrs->search({ title => 'Thriller' })->as_query },
+      ],
+    },
+  );
+
+  my $arr = $rs->as_query;
+  my ($query, @bind) = @{$$arr};
+  is_same_sql_bind(
+    $query, \@bind,
+    "(SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (SELECT me.cdid,me.artist,me.title,me.year,me.genreid,me.single_track FROM cd me WHERE title = ?) cd2)",
+    [
+      [ 'title',
+        'Thriller'
+      ]
+    ],
+  );
+}
+
 __END__




More information about the Bast-commits mailing list