error checking related to literal SQL for insert_bulk
[dbsrgits/DBIx-Class.git] / t / 100populate.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Test::Exception;
6 use lib qw(t/lib);
7 use DBICTest;
8
9 my $schema = DBICTest->init_schema();
10
11 # The map below generates stuff like:
12 #   [ qw/artistid name/ ],
13 #   [ 4, "b" ],
14 #   [ 5, "c" ],
15 #   ...
16 #   [ 9999, "ntm" ],
17 #   [ 10000, "ntn" ],
18
19 my $start_id = 'populateXaaaaaa';
20 my $rows = 10;
21 my $offset = 3;
22
23 $schema->populate('Artist', [ [ qw/artistid name/ ], map { [ ($_ + $offset) => $start_id++ ] } ( 1 .. $rows ) ] );
24 is (
25     $schema->resultset ('Artist')->search ({ name => { -like => 'populateX%' } })->count,
26     $rows,
27     'populate created correct number of rows with massive AoA bulk insert',
28 );
29
30 my $artist = $schema->resultset ('Artist')
31               ->search ({ 'cds.title' => { '!=', undef } }, { join => 'cds' })
32                 ->first;
33 my $ex_title = $artist->cds->first->title;
34
35 throws_ok ( sub {
36   my $i = 600;
37   $schema->populate('CD', [
38     map {
39       {
40         artist => $artist->id,
41         title => $_,
42         year => 2009,
43       }
44     } ('Huey', 'Dewey', $ex_title, 'Louie')
45   ])
46 }, qr/columns .+ are not unique for populate slice.+$ex_title/ms, 'Readable exception thrown for failed populate');
47
48 ## make sure populate honors fields/orders in list context
49 ## schema order
50 my @links = $schema->populate('Link', [
51 [ qw/id url title/ ],
52 [ qw/2 burl btitle/ ]
53 ]);
54 is(scalar @links, 1);
55
56 my $link2 = shift @links;
57 is($link2->id, 2, 'Link 2 id');
58 is($link2->url, 'burl', 'Link 2 url');
59 is($link2->title, 'btitle', 'Link 2 title');
60
61 ## non-schema order
62 @links = $schema->populate('Link', [
63 [ qw/id title url/ ],
64 [ qw/3 ctitle curl/ ]
65 ]);
66 is(scalar @links, 1);
67
68 my $link3 = shift @links;
69 is($link3->id, 3, 'Link 3 id');
70 is($link3->url, 'curl', 'Link 3 url');
71 is($link3->title, 'ctitle', 'Link 3 title');
72
73 ## not all physical columns
74 @links = $schema->populate('Link', [
75 [ qw/id title/ ],
76 [ qw/4 dtitle/ ]
77 ]);
78 is(scalar @links, 1);
79
80 my $link4 = shift @links;
81 is($link4->id, 4, 'Link 4 id');
82 is($link4->url, undef, 'Link 4 url');
83 is($link4->title, 'dtitle', 'Link 4 title');
84
85
86 ## make sure populate -> insert_bulk honors fields/orders in void context
87 ## schema order
88 $schema->populate('Link', [
89 [ qw/id url title/ ],
90 [ qw/5 eurl etitle/ ]
91 ]);
92 my $link5 = $schema->resultset('Link')->find(5);
93 is($link5->id, 5, 'Link 5 id');
94 is($link5->url, 'eurl', 'Link 5 url');
95 is($link5->title, 'etitle', 'Link 5 title');
96
97 ## non-schema order
98 $schema->populate('Link', [
99 [ qw/id title url/ ],
100 [ qw/6 ftitle furl/ ]
101 ]);
102 my $link6 = $schema->resultset('Link')->find(6);
103 is($link6->id, 6, 'Link 6 id');
104 is($link6->url, 'furl', 'Link 6 url');
105 is($link6->title, 'ftitle', 'Link 6 title');
106
107 ## not all physical columns
108 $schema->populate('Link', [
109 [ qw/id title/ ],
110 [ qw/7 gtitle/ ]
111 ]);
112 my $link7 = $schema->resultset('Link')->find(7);
113 is($link7->id, 7, 'Link 7 id');
114 is($link7->url, undef, 'Link 7 url');
115 is($link7->title, 'gtitle', 'Link 7 title');
116
117 # test _execute_array_empty (insert_bulk with all literal sql)
118 my $rs = $schema->resultset('Artist');
119 $rs->delete;
120 $rs->populate([
121     (+{
122         name => \"'DT'",
123         rank => \500,
124         charfield => \"'mtfnpy'",
125     }) x 5
126 ]);
127
128 is((grep {
129   $_->name eq 'DT' &&
130   $_->rank == 500  &&
131   $_->charfield eq 'mtfnpy'
132 } $rs->all), 5, 'populate with all literal SQL');
133
134 $rs->delete;
135
136 throws_ok {
137     $rs->populate([
138         {
139             artistid => 1,
140             name => 'foo1',
141         },
142         {
143             artistid => 'foo', # this dies
144             name => 'foo2',
145         },
146         {
147             artistid => 3,
148             name => 'foo3',
149         },
150     ]);
151 } qr/slice/, 'bad slice';
152
153 is($rs->count, 0, 'populate is atomic');
154
155 # Trying to use a column marked as a bind in the first slice with literal sql in
156 # a later slice should throw.
157
158 throws_ok {
159   $rs->populate([
160     {
161       artistid => 1,
162       name => \"'foo'",
163     },
164     {
165       artistid => \2,
166       name => \"'foo'",
167     }
168   ]);
169 } qr/bind expected/, 'literal sql where bind expected throws';
170
171 # ... and vice-versa.
172
173 throws_ok {
174   $rs->populate([
175     {
176       artistid => \1,
177       name => \"'foo'",
178     },
179     {
180       artistid => 2,
181       name => \"'foo'",
182     }
183   ]);
184 } qr/literal SQL expected/i, 'bind where literal sql expected throws';
185
186 throws_ok {
187   $rs->populate([
188     {
189       artistid => 1,
190       name => \"'foo'",
191     },
192     {
193       artistid => 2,
194       name => \"'bar'",
195     }
196   ]);
197 } qr/inconsistent/, 'literal sql must be the same in all slices';
198
199 done_testing;