Move the infmap verification/exception way earlier
[dbsrgits/DBIx-Class.git] / t / sqlmaker / limit_dialects / rownum.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5
6 use lib qw(t/lib);
7 use DBICTest;
8 use DBIC::SqlMakerTest;
9 use DBIx::Class::SQLMaker::LimitDialects;
10
11 my ($TOTAL, $OFFSET, $ROWS) = (
12    DBIx::Class::SQLMaker::LimitDialects->__total_bindtype,
13    DBIx::Class::SQLMaker::LimitDialects->__offset_bindtype,
14    DBIx::Class::SQLMaker::LimitDialects->__rows_bindtype,
15 );
16
17 my $s = DBICTest->init_schema (no_deploy => 1, );
18 $s->storage->sql_maker->limit_dialect ('RowNum');
19
20 my $rs = $s->resultset ('CD')->search({ id => 1 });
21
22 # important for a test below, never traversed
23 $rs->result_source->add_relationship(
24   ends_with_me => 'DBICTest::Schema::Artist', sub {}
25 );
26
27
28 my $where_bind = [ { dbic_colname => 'id' }, 1 ];
29
30 for my $test_set (
31   {
32     name => 'Rownum subsel aliasing works correctly',
33     rs => $rs->search_rs(undef, {
34       rows => 1,
35       offset => 3,
36       columns => [
37         { id => 'foo.id' },
38         { 'artist.id' => 'bar.id' },
39         { bleh => \'TO_CHAR (foo.womble, "blah")' },
40       ]
41     }),
42     sql => '(
43       SELECT id, artist__id, bleh
44       FROM (
45         SELECT id, artist__id, bleh, ROWNUM rownum__index
46         FROM (
47           SELECT foo.id AS id, bar.id AS artist__id, TO_CHAR (foo.womble, "blah") AS bleh
48             FROM cd me
49           WHERE id = ?
50         ) me
51       ) me WHERE rownum__index BETWEEN ? AND ?
52     )',
53     binds => [
54       $where_bind,
55       [ $OFFSET => 4 ],
56       [ $TOTAL => 4 ],
57     ],
58   }, {
59     name => 'Rownum subsel aliasing works correctly with unique order_by',
60     rs => $rs->search_rs(undef, {
61       rows => 1,
62       offset => 3,
63       columns => [
64         { id => 'foo.id' },
65         { 'artist.id' => 'bar.id' },
66         { bleh => \'TO_CHAR (foo.womble, "blah")' },
67       ],
68       order_by => [qw( artist title )],
69     }),
70     sql => '(
71       SELECT id, artist__id, bleh
72       FROM (
73         SELECT id, artist__id, bleh, ROWNUM rownum__index
74         FROM (
75           SELECT foo.id AS id, bar.id AS artist__id, TO_CHAR(foo.womble, "blah") AS bleh
76             FROM cd me
77           WHERE id = ?
78           ORDER BY artist, title
79         ) me
80         WHERE ROWNUM <= ?
81       ) me
82       WHERE rownum__index >= ?
83     )',
84     binds => [
85       $where_bind,
86       [ $TOTAL => 4 ],
87       [ $OFFSET => 4 ],
88     ],
89   },
90  {
91     name => 'Rownum subsel aliasing works correctly with non-unique order_by',
92     rs => $rs->search_rs(undef, {
93       rows => 1,
94       offset => 3,
95       columns => [
96         { id => 'foo.id' },
97         { 'artist.id' => 'bar.id' },
98         { bleh => \'TO_CHAR (foo.womble, "blah")' },
99       ],
100       order_by => 'artist',
101     }),
102     sql => '(
103       SELECT id, artist__id, bleh
104       FROM (
105         SELECT id, artist__id, bleh, ROWNUM rownum__index
106         FROM (
107           SELECT foo.id AS id, bar.id AS artist__id, TO_CHAR(foo.womble, "blah") AS bleh
108             FROM cd me
109           WHERE id = ?
110           ORDER BY artist
111         ) me
112       ) me
113       WHERE rownum__index BETWEEN ? and ?
114     )',
115     binds => [
116       $where_bind,
117       [ $OFFSET => 4 ],
118       [ $TOTAL => 4 ],
119     ],
120   }, {
121     name => 'Rownum subsel aliasing #2 works correctly',
122     rs => $rs->search_rs(undef, {
123       rows => 2,
124       offset => 3,
125       columns => [
126         { id => 'foo.id' },
127         { 'ends_with_me.id' => 'ends_with_me.id' },
128       ]
129     }),
130     sql => '(
131       SELECT id, ends_with_me__id
132       FROM (
133         SELECT id, ends_with_me__id, ROWNUM rownum__index
134         FROM (
135           SELECT foo.id AS id, ends_with_me.id AS ends_with_me__id
136             FROM cd me
137           WHERE id = ?
138         ) me
139       ) me WHERE rownum__index BETWEEN ? AND ?
140     )',
141     binds => [
142       $where_bind,
143       [ $OFFSET => 4 ],
144       [ $TOTAL => 5 ],
145     ],
146   }, {
147     name => 'Rownum subsel aliasing #2 works correctly with unique order_by',
148     rs => $rs->search_rs(undef, {
149       rows => 2,
150       offset => 3,
151       columns => [
152         { id => 'foo.id' },
153         { 'ends_with_me.id' => 'ends_with_me.id' },
154       ],
155       order_by => [qw( year artist title )],
156     }),
157     sql => '(
158       SELECT id, ends_with_me__id
159       FROM (
160         SELECT id, ends_with_me__id, ROWNUM rownum__index
161         FROM (
162           SELECT foo.id AS id, ends_with_me.id AS ends_with_me__id
163             FROM cd me
164           WHERE id = ?
165           ORDER BY year, artist, title
166         ) me
167         WHERE ROWNUM <= ?
168       ) me
169       WHERE rownum__index >= ?
170     )',
171     binds => [
172       $where_bind,
173       [ $TOTAL => 5 ],
174       [ $OFFSET => 4 ],
175     ],
176   }
177 ) {
178   is_same_sql_bind(
179     $test_set->{rs}->as_query,
180     $test_set->{sql},
181     $test_set->{binds},
182     $test_set->{name});
183 }
184
185 {
186 my $subq = $s->resultset('Owners')->search({
187    'count.id' => { -ident => 'owner.id' },
188 }, { alias => 'owner' })->count_rs;
189
190 my $rs_selectas_rel = $s->resultset('BooksInLibrary')->search ({}, {
191   columns => [
192      { owner_name => 'owner.name' },
193      { owner_books => $subq->as_query },
194   ],
195   join => 'owner',
196   rows => 2,
197   offset => 3,
198 });
199
200 is_same_sql_bind(
201   $rs_selectas_rel->as_query,
202   '(
203     SELECT owner_name, owner_books
204       FROM (
205         SELECT owner_name, owner_books, ROWNUM rownum__index
206           FROM (
207             SELECT  owner.name AS owner_name,
208               ( SELECT COUNT( * ) FROM owners owner WHERE (count.id = owner.id)) AS owner_books
209               FROM books me
210               JOIN owners owner ON owner.id = me.owner
211             WHERE ( source = ? )
212           ) me
213       ) me
214     WHERE rownum__index BETWEEN ? AND ?
215   )',
216   [
217     [ { sqlt_datatype => 'varchar', sqlt_size => 100, dbic_colname => 'source' }
218       => 'Library' ],
219     [ $OFFSET => 4 ],
220     [ $TOTAL => 5 ],
221   ],
222
223   'pagination with subquery works'
224 );
225
226 }
227
228 {
229   $rs = $s->resultset('Artist')->search({}, {
230     columns => 'name',
231     offset => 1,
232     order_by => 'name',
233   });
234   local $rs->result_source->{name} = "weird \n newline/multi \t \t space containing \n table";
235
236   like (
237     ${$rs->as_query}->[0],
238     qr| weird \s \n \s newline/multi \s \t \s \t \s space \s containing \s \n \s table|x,
239     'Newlines/spaces preserved in final sql',
240   );
241 }
242
243 {
244 my $subq = $s->resultset('Owners')->search({
245    'books.owner' => { -ident => 'owner.id' },
246 }, { alias => 'owner', select => ['id'] } )->count_rs;
247
248 my $rs_selectas_rel = $s->resultset('BooksInLibrary')->search( { -exists => $subq->as_query }, { select => ['id','owner'], rows => 1 } );
249
250 is_same_sql_bind(
251   $rs_selectas_rel->as_query,
252   '(
253     SELECT me.id, me.owner FROM (
254       SELECT me.id, me.owner  FROM books me WHERE ( ( (EXISTS (SELECT COUNT( * ) FROM owners owner WHERE ( books.owner = owner.id ))) AND source = ? ) )
255     ) me
256     WHERE ROWNUM <= ?
257   )',
258   [
259     [ { sqlt_datatype => 'varchar', sqlt_size => 100, dbic_colname => 'source' } => 'Library' ],
260     [ $ROWS => 1 ],
261   ],
262   'Pagination with sub-query in WHERE works'
263 );
264
265 }
266
267 done_testing;