Major overhaul of select/as resolution handling (fixes RT#61235)
[dbsrgits/DBIx-Class.git] / t / search / subquery.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
10 my $schema = DBICTest->init_schema();
11 my $art_rs = $schema->resultset('Artist');
12 my $cdrs = $schema->resultset('CD');
13
14 my @tests = (
15   {
16     rs => $cdrs,
17     search => \[ "title = ? AND year LIKE ?", [ title => 'buahaha' ], [ year => '20%' ] ],
18     attrs => { rows => 5 },
19     sqlbind => \[
20       "( SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE (title = ? AND year LIKE ?) LIMIT 5)",
21       [ title => 'buahaha' ],
22       [ year => '20%' ],
23     ],
24   },
25
26   {
27     rs => $cdrs,
28     search => {
29       artist_id => { 'in' => $art_rs->search({}, { rows => 1 })->get_column( 'id' )->as_query },
30     },
31     sqlbind => \[
32       "( SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE artist_id IN ( SELECT me.id FROM artist me LIMIT 1 ) )",
33     ],
34   },
35
36   {
37     rs => $art_rs,
38     attrs => {
39       'select' => [
40         $cdrs->search({}, { rows => 1 })->get_column('id')->as_query,
41       ],
42     },
43     sqlbind => \[
44       "( SELECT (SELECT me.id FROM cd me LIMIT 1) FROM artist me )",
45     ],
46   },
47
48   {
49     rs => $art_rs,
50     attrs => {
51       '+select' => [
52         $cdrs->search({}, { rows => 1 })->get_column('id')->as_query,
53       ],
54     },
55     sqlbind => \[
56       "( SELECT me.artistid, me.name, me.rank, me.charfield, (SELECT me.id FROM cd me LIMIT 1) FROM artist me )",
57     ],
58   },
59
60   {
61     rs => $cdrs,
62     attrs => {
63       alias => 'cd2',
64       from => [
65         { cd2 => $cdrs->search({ id => { '>' => 20 } })->as_query },
66       ],
67     },
68     sqlbind => \[
69       "( SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (
70             SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE id > ?
71           ) cd2
72         )",
73       [ 'id', 20 ]
74     ],
75   },
76
77   {
78     rs => $art_rs,
79     attrs => {
80       from => [
81         { 'me' => 'artist' },
82         [
83           { 'cds' => $cdrs->search({}, { 'select' => [\'me.artist as cds_artist' ]})->as_query },
84           { 'me.artistid' => 'cds_artist' } 
85         ]
86       ]
87     },
88     sqlbind => \[
89       "( 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 )"
90     ],
91   },
92
93   {
94     rs => $cdrs,
95     attrs => {
96       alias => 'cd2',
97       from => [
98         { cd2 => $cdrs->search(
99             { id => { '>' => 20 } }, 
100             { 
101                 alias => 'cd3',
102                 from => [ 
103                 { cd3 => $cdrs->search( { id => { '<' => 40 } } )->as_query }
104                 ],
105             }, )->as_query },
106       ],
107     },
108     sqlbind => \[
109       "( SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track
110         FROM
111           (SELECT cd3.cdid, cd3.artist, cd3.title, cd3.year, cd3.genreid, cd3.single_track
112             FROM
113               (SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
114                 FROM cd me WHERE id < ?) cd3
115             WHERE id > ?) cd2
116       )",
117       [ 'id', 40 ],
118       [ 'id', 20 ]
119     ],
120   },
121
122   {
123     rs => $cdrs,
124     search => {
125       year => {
126         '=' => $cdrs->search(
127           { artistid => { '=' => \'me.artistid' } },
128           { alias => 'inner' }
129         )->get_column('year')->max_rs->as_query,
130       },
131     },
132     sqlbind => \[
133       "( 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) )",
134     ],
135   },
136
137   {
138     rs => $cdrs,
139     attrs => {
140       alias => 'cd2',
141       from => [
142         { cd2 => $cdrs->search({ title => 'Thriller' })->as_query },
143       ],
144     },
145     sqlbind => \[
146       "(SELECT cd2.cdid, cd2.artist, cd2.title, cd2.year, cd2.genreid, cd2.single_track FROM (
147           SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE title = ?
148         ) cd2
149       )",
150       [ 'title',
151         'Thriller'
152       ]
153     ],
154   },
155 );
156
157
158 for my $i (0 .. $#tests) {
159   my $t = $tests[$i];
160   for my $p (1, 2) {  # repeat everything twice, make sure we do not clobber search arguments
161     is_same_sql_bind (
162       $t->{rs}->search ($t->{search}, $t->{attrs})->as_query,
163       $t->{sqlbind},
164       sprintf 'Testcase %d, pass %d', $i+1, $p,
165     );
166   }
167 }
168
169 done_testing;