From: Peter Rabbitson Date: Sat, 21 Apr 2012 04:33:11 +0000 (+0200) Subject: More limit torture X-Git-Tag: v0.08197~20 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=66458d5da48654e8f8558d16ce9857e5129c4dac;p=dbsrgits%2FDBIx-Class.git More limit torture --- diff --git a/t/sqlmaker/limit_dialects/torture.t b/t/sqlmaker/limit_dialects/torture.t index 7956f52..3b72154 100644 --- a/t/sqlmaker/limit_dialects/torture.t +++ b/t/sqlmaker/limit_dialects/torture.t @@ -2,11 +2,13 @@ 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; +my $native_limit_dialect = $schema->storage->sql_maker->{limit_dialect}; my $attr = {}; my @where_bind = ( @@ -53,6 +55,23 @@ my $tests = { [ { sqlt_datatype => 'integer' } => 3 ], ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT me.name, me.id + FROM owners me + LIMIT ? OFFSET ? + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 3 ], + [ { sqlt_datatype => 'integer' } => 1 ], + ] + ], }, LimitXY => { @@ -78,6 +97,23 @@ my $tests = { [ { sqlt_datatype => 'integer' } => 4 ], ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT me.name, me.id + FROM owners me + LIMIT ?,? + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 1 ], + [ { sqlt_datatype => 'integer' } => 3 ], + ] + ], }, SkipFirst => { @@ -102,6 +138,22 @@ my $tests = { @order_bind, ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT SKIP ? FIRST ? me.name, me.id + FROM owners me + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 1 ], + [ { sqlt_datatype => 'integer' } => 3 ], + ] + ], }, FirstSkip => { @@ -126,6 +178,22 @@ my $tests = { @order_bind, ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT FIRST ? SKIP ? me.name, me.id + FROM owners me + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 3 ], + [ { sqlt_datatype => 'integer' } => 1 ], + ] + ], }, RowNumberOver => do { @@ -207,6 +275,28 @@ my $tests = { [ { sqlt_datatype => 'integer' } => 7 ], ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT me.name, me.id + FROM ( + SELECT me.name, me.id, ROW_NUMBER() OVER() AS rno__row__index + FROM ( + SELECT me.name, me.id FROM owners me + ) me + ) me + WHERE rno__row__index >= ? AND rno__row__index <= ? + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 2 ], + [ { sqlt_datatype => 'integer' } => 4 ], + ] + ], }; }, @@ -303,6 +393,28 @@ my $tests = { [ { sqlt_datatype => 'integer' } => 4 ], ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT me.name, me.id + FROM ( + SELECT me.name, me.id, ROWNUM rownum__index + FROM ( + SELECT me.name, me.id + FROM owners me + ) me + ) me WHERE rownum__index BETWEEN ? AND ? + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 2 ], + [ { sqlt_datatype => 'integer' } => 4 ], + ] + ], }; }, @@ -399,6 +511,26 @@ my $tests = { (map { [ @$_ ] } @order_bind), # without this is_deeply throws a fit ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT me.name, me.id + FROM ( + SELECT me.name, me.id + FROM owners me + ORDER BY me.id + FETCH FIRST 4 ROWS ONLY + ) me + ORDER BY me.id DESC + FETCH FIRST 3 ROWS ONLY + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [], + ], }, Top => { @@ -488,6 +620,24 @@ my $tests = { (map { [ @$_ ] } @order_bind), # without this is_deeply throws a fit ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT TOP 3 me.name, me.id + FROM ( + SELECT TOP 4 me.name, me.id + FROM owners me + ORDER BY me.id + ) me + ORDER BY me.id DESC + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [], + ], }, RowCountOrGenericSubQ => { @@ -597,6 +747,30 @@ my $tests = { [ { sqlt_datatype => 'integer' } => 6 ], ], ], + limit_offset_prefetch => [ + '( + SELECT me.name, books.id, books.source, books.owner, books.title, books.price + FROM ( + SELECT me.name, me.id + FROM ( + SELECT me.name, me.id FROM owners me + ) me + WHERE ( + SELECT COUNT(*) + FROM owners rownum__emulation + WHERE rownum__emulation.id < me.id + ) BETWEEN ? AND ? + ORDER BY me.id + ) me + LEFT JOIN books books + ON books.owner = me.id + ORDER BY me.id + )', + [ + [ { sqlt_datatype => 'integer' } => 1 ], + [ { sqlt_datatype => 'integer' } => 3 ], + ], + ], } }; @@ -653,6 +827,27 @@ for my $limtype (sort keys %$tests) { @{$tests->{$limtype}{ordered_limit_offset}}, "$limtype: Ordered limit+offset with select/group/having", ) if $tests->{$limtype}{ordered_limit_offset}; + + # complex prefetch on partial-fetch root with limit + my $pref_rs = $schema->resultset('Owners')->search({}, { + rows => 3, + offset => 1, + columns => 'name', # only the owner name, still prefetch all the books + prefetch => 'books', + ($limtype =~ /GenericSubQ/ ? ( order_by => 'me.id' ) : () ), # needs a simple-column stable order to be happy + }); + + is_same_sql_bind ( + $pref_rs->as_query, + @{$tests->{$limtype}{limit_offset_prefetch}}, + "$limtype: Prefetch with limit+offset", + ) if $tests->{$limtype}{limit_offset_prefetch}; + + # we can actually run the query + if ($limtype eq $native_limit_dialect or $limtype eq 'GenericSubQ') { + lives_ok { is ($pref_rs->all, 1, 'Expected count of objects on limtied prefetch') } + "Complex limited prefetch works with supported limit $limtype" + } } done_testing;