sybase limit count without offset now works
Rafael Kitover [Thu, 4 Jun 2009 12:50:49 +0000 (12:50 +0000)]
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBI/Sybase.pm
lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm
lib/DBIx/Class/Storage/DBI/Sybase/NoBindVars.pm
t/746sybase.t

index f7ba454..f3ea456 100644 (file)
@@ -926,6 +926,22 @@ sub _fix_bind_params {
         } @bind;
 }
 
+sub _flatten_bind_params {
+    my ($self, @bind) = @_;
+
+    ### Turn @bind from something like this:
+    ###   ( [ "artist", 1 ], [ "cdid", 1, 3 ] )
+    ### to this:
+    ###   ( 1, 1, 3 )
+    return
+        map {
+            if ( defined( $_ && $_->[1] ) ) {
+                @{$_}[ 1 .. $#$_ ];
+            }
+            else { undef; }
+        } @bind;
+}
+
 sub _query_start {
     my ( $self, $sql, @bind ) = @_;
 
@@ -1229,16 +1245,25 @@ sub _select_args {
   return @args;
 }
 
-sub count {
+sub _trim_attributes_for_count {
   my ($self, $source, $attrs) = @_;
+  my %attrs = %$attrs;
 
   # take off any column specs, any pagers, record_filter is cdbi, and no point of ordering a count
-  delete $attrs->{$_} for (qw/columns +columns select +select as +as rows offset page pager order_by record_filter/);
+  delete $attrs{$_} for (qw/columns +columns select +select as +as rows offset page pager order_by record_filter/);
+
+  return \%attrs;
+}
+
+sub count {
+  my ($self, $source, $attrs) = @_;
+
+  my $new_attrs = $self->_trim_attributes_for_count($source, $attrs);
 
-  $attrs->{select} = { count => '*' };
-  $attrs->{as} = [qw/count/];
+  $new_attrs->{select} = { count => '*' };
+  $new_attrs->{as} = [qw/count/];
 
-  my $tmp_rs = $source->resultset_class->new($source, $attrs);
+  my $tmp_rs = $source->resultset_class->new($source, $new_attrs);
   my ($count) = $tmp_rs->cursor->next;
 
   return $count;
index 5220dac..e5acf8d 100644 (file)
@@ -59,6 +59,36 @@ sub _dbh_last_insert_id {
   return ($dbh->selectrow_array($sth))[0];
 }
 
+sub count {
+  my ($self, $source, $attrs) = @_;
+
+  if (exists $attrs->{rows}) {
+    my $new_attrs = $self->_trim_attributes_for_count($source, $attrs);
+
+    $new_attrs->{select} = '1';
+    $new_attrs->{as}     = ['dummy'];
+
+# speed things up at least *a little*
+    $new_attrs->{result_class} = 'DBIx::Class::ResultClass::HashRefInflator';
+
+    my $offset = $attrs->{offset} || 0;
+    my $total  = $attrs->{rows} + $offset;
+    
+    $self->dbh->do("set rowcount $total");
+
+    my $tmp_rs = $source->resultset_class->new($source, $new_attrs);
+    
+    my $count = 0;
+    $count++ while $tmp_rs->cursor->next;
+
+    $self->dbh->do("set rowcount 0");
+
+    return $count;
+  }
+
+  return $self->next::method(@_);
+}
+
 sub datetime_parser_type { "DBIx::Class::Storage::DBI::Sybase::DateTime" }
 
 1;
@@ -90,6 +120,9 @@ On connection C<syb_date_fmt> is set to C<ISO_strict>, e.g.:
 C<2004-08-21T14:36:48.080Z> and C<dateformat> is set to C<mdy>, e.g.:
 C<08/13/1979 18:08:55.080>.
 
+This works for both C<DATETIME> and C<SMALLDATETIME> columns, although
+C<SMALLDATETIME> columns only have minute precision.
+
 You will need the L<DateTime::Format::Strptime> module if you are going to use
 L<DBIx::Class::InflateColumn::DateTime>.
 
index f458b91..cbde13d 100644 (file)
@@ -3,6 +3,7 @@ package DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server;
 use strict;
 use warnings;
 
+use Class::C3;
 use base qw/
   DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server
   DBIx::Class::Storage::DBI::NoBindVars
@@ -33,9 +34,7 @@ L<DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server>.
 
 =head1 AUTHORS
 
-Brandon L Black <blblack@gmail.com>
-
-Justin Hunter <justin.d.hunter@gmail.com>
+See L<DBIx::Class/CONTRIBUTORS>.
 
 =head1 LICENSE
 
index b5d61a2..1f5dfc4 100644 (file)
@@ -1,5 +1,6 @@
 package DBIx::Class::Storage::DBI::Sybase::NoBindVars;
 
+use Class::C3;
 use base qw/
   DBIx::Class::Storage::DBI::NoBindVars
   DBIx::Class::Storage::DBI::Sybase
index 47064af..3a4ebb9 100644 (file)
@@ -62,16 +62,15 @@ SQL
     $seen_id{$new->artistid}++;
   }
 
-  my $it = $schema->resultset('Artist')->search( {}, {
+## avoid quoting bug with NoBindVars for now
+#  my $it = $schema->resultset('Artist')->search({artistid => { '>' => 0 }}, {
+
+  my $it = $schema->resultset('Artist')->search({}, {
     rows => 3,
     order_by => 'artistid',
   });
 
-  TODO: {
-    local $TODO = 'Sybase is very very fucked in the limit department';
-
-    is( $it->count, 3, "LIMIT count ok" );
-  }
+  is( $it->count, 3, "LIMIT count ok" );
 
   is( $it->next->name, "foo", "iterator->next ok" );
   $it->next;