Document software_limit and properly throw on related as_query calls
Peter Rabbitson [Sat, 14 Apr 2012 12:03:20 +0000 (14:03 +0200)]
Changes
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/SQLMaker/LimitDialects.pm
lib/DBIx/Class/Storage/DBI.pm
t/sqlmaker/limit_dialects/basic.t [moved from t/75limit.t with 88% similarity]

diff --git a/Changes b/Changes
index ab85ce1..f3515dc 100644 (file)
--- a/Changes
+++ b/Changes
@@ -29,6 +29,8 @@ Revision history for DBIx::Class
           when we both select and order by the result of the same subquery
         - Fix the Sybase hubrid limit dialect (RowCountOrGenericSubQ) losing
           Group/Having/Order clauses when called without an offset (RT#73244)
+        - No longer generate incorrect SQL on ->as_query called on resultsets
+          with software_limit enabled
         - A number of corner case fixes of void context populate() with \[]
         - Fix corner case of forked children disconnecting the parents DBI
           handle
index 71595e3..0d6906f 100644 (file)
@@ -4231,6 +4231,24 @@ rows per page if the page attribute or method is used.
 Specifies the (zero-based) row number for the  first row to be returned, or the
 of the first row of the first page if paging is used.
 
+=head2 software_limit
+
+=over 4
+
+=item Value: (0 | 1)
+
+=back
+
+When combined with L</rows> and/or L</offset> the generated SQL will not
+include any limit dialect stanzas. Instead the entire result will be selected
+as if no limits were specified, and DBIC will perform the limit locally, by
+artificially advancing and finishing the resulting L</cursor>.
+
+This is the recommended way of performing resultset limiting when no sane RDBMS
+implementation is available (e.g.
+L<Sybase ASE|DBIx::Class::Storage::DBI::Sybase::ASE> using the
+L<Generic Sub Query|DBIx::Class::SQLMaker::LimitDialects/GenericSubQ> hack)
+
 =head2 group_by
 
 =over 4
index 84cc5a3..a0ea4ef 100644 (file)
@@ -557,8 +557,11 @@ This is the most evil limit "dialect" (more of a hack) for I<really> stupid
 databases. It works by ordering the set by some unique column, and calculating
 the amount of rows that have a less-er value (thus emulating a L</RowNum>-like
 index). Of course this implies the set can only be ordered by a single unique
-column. Also note that this technique can be and often is B<excruciatingly
-slow>.
+column.
+
+Also note that this technique can be and often is B<excruciatingly slow>. You
+may have much better luck using L<DBIx::Class::ResultSet/software_limit>
+instead.
 
 Currently used by B<Sybase ASE>, due to lack of any other option.
 
index 1566fec..b107d24 100644 (file)
@@ -2118,6 +2118,10 @@ sub _select {
 sub _select_args_to_query {
   my $self = shift;
 
+  $self->throw_exception(
+    "Unable to generate limited query representation with 'software_limit' enabled"
+  ) if ($_[3]->{software_limit} and ($_[3]->{offset} or $_[3]->{rows}) );
+
   # my ($op, $ident, $select, $cond, $rs_attrs, $rows, $offset)
   #  = $self->_select_args($ident, $select, $cond, $attrs);
   my ($op, $ident, @args) =
similarity index 88%
rename from t/75limit.t
rename to t/sqlmaker/limit_dialects/basic.t
index 61f5520..7098f1d 100644 (file)
@@ -2,6 +2,7 @@ use strict;
 use warnings;
 
 use Test::More;
+use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
@@ -46,6 +47,12 @@ is( $it->next, undef, "software next past end of resultset ok" );
 );
 is( $cds[0]->title, "Spoonful of bees", "software offset ok" );
 
+throws_ok {
+  $schema->resultset("CD")->search({}, {
+    rows => 2,
+    software_limit => 1,
+  })->as_query;
+} qr/Unable to generate limited query representation with 'software_limit' enabled/;
 
 @cds = $schema->resultset("CD")->search( {},
     {
@@ -54,9 +61,6 @@ is( $cds[0]->title, "Spoonful of bees", "software offset ok" );
 );
 is( $cds[0]->title, "Spoonful of bees", "offset with no limit" );
 
-
-# based on a failing criteria submitted by waswas
-# requires SQL::Abstract >= 1.20
 $it = $schema->resultset("CD")->search(
     { title => [
         -and =>