Codebase list libdbix-class-resultset-recursiveupdate-perl / 7911d81
fix updating many_to_many relationship helpers when the foreign relationship is named differently than the foreign key column Alexander Hartmaier 3 years ago
5 changed file(s) with 499 addition(s) and 210 deletion(s). Raw diff Collapse all Expand all
22 {{ $NEXT }}
33 - Fix side effects like change column_info and usage of each
44 - Silence uninitialized value warnings
5 - Fix updating many_to_many relationship helpers when the foreign
6 relationship is named differently than the foreign key column
57
68 0.41 2020-05-13 13:13:33+02:00 Europe/Vienna
79 - Fix missing Test::Exception test dependency
531531 }
532532 my $related_object;
533533
534 my @missing_pks = grep {
535 my $pkcolname = $_;
536 none { $_ eq $pkcolname } keys %pk_kvs;
537 } @pks;
538
534539 # support the special case where a method on the related row
535540 # populates one or more primary key columns and we don't have
536541 # all primary key values already
537542 # see DBSchema::Result::DVD relationship keysbymethod
538543 DEBUG and warn "pk columns so far: " . join (', ',
539544 sort keys %pk_kvs) . "\n";
545 DEBUG and warn "pk columns missing: " . join (', ',
546 sort @missing_pks) . "\n";
540547 my @non_pk_columns = grep {
541548 my $colname = $_;
542549 none { $colname eq $_ } keys %pk_kvs
544551 sort keys %$sub_updates;
545552 DEBUG and warn "non-pk columns: " . join (', ',
546553 @non_pk_columns) . "\n";
554 if ( scalar keys %pk_kvs != scalar @pks && @non_pk_columns) {
555 DEBUG and warn "not all primary keys available, trying " .
556 "relationships\n";
557 my @rel_names = grep {
558 $related_result_source->has_relationship($_)
559 } sort keys %$sub_updates;
560
561 for my $relname (@rel_names) {
562 my $rel_info = $related_result_source
563 ->relationship_info($relname);
564 next
565 unless $rel_info->{attrs}->{accessor} eq 'single'
566 && $rel_info->{attrs}->{is_foreign_key_constraint};
567
568 for my $f_key ( sort keys %{$rel_info->{cond}} ) {
569 my $col = $rel_info->{cond}->{$f_key};
570 $col =~ s/^self\.//;
571 $f_key =~ s/^foreign\.//;
572
573 next
574 unless any { $col eq $_ } @missing_pks;
575
576 DEBUG and warn "populating primary key column " .
577 "'$col' from relationship '$relname'\n";
578 # rel holds a scalar value
579 if (keys %{$rel_info->{cond}} == 1 && !ref $sub_updates->{$relname}) {
580 $pk_kvs{$col} = delete $sub_updates->{$relname};
581 # optimization to not update the related row
582 # when only the primary key of it is given
583 $sub_updates->{$col} = $pk_kvs{$col};
584 }
585 # rel holds a hashref
586 elsif (ref $sub_updates->{$relname} eq 'HASH') {
587 $pk_kvs{$col} =
588 $sub_updates->{$relname}->{$f_key};
589 }
590 else {
591 $self->throw_exception("passing anything else " .
592 "but a scalar or a hashref is not " .
593 "implemented");
594 }
595 }
596 }
597 }
598
547599 if ( scalar keys %pk_kvs != scalar @pks && @non_pk_columns) {
548600 DEBUG and warn "not all primary keys available, trying " .
549601 "object creation\n";
4545 __PACKAGE__->has_many('dvdtags', 'Dvdtag', { 'foreign.dvd' => 'self.dvd_id' });
4646 __PACKAGE__->has_many('viewings', 'DBSchema::Result::Viewing', { 'foreign.dvd_id' => 'self.dvd_id' });
4747 __PACKAGE__->many_to_many('tags', 'dvdtags' => 'tag');
48 # same relationship with a name that's different from the column name
49 __PACKAGE__->many_to_many('rel_tags', 'dvdtags' => 'rel_tag');
4850 __PACKAGE__->might_have(
4951 liner_notes => 'DBSchema::Result::LinerNotes', undef,
5052 { proxy => [ qw/notes/ ] },
1515 __PACKAGE__->set_primary_key("dvd", "tag");
1616 __PACKAGE__->belongs_to("dvd", "DBSchema::Result::Dvd", { dvd_id => "dvd" });
1717 __PACKAGE__->belongs_to("tag", "DBSchema::Result::Tag", { id => "tag" });
18 # same relationship with a name that's different from the column name
19 __PACKAGE__->belongs_to("rel_tag", "DBSchema::Result::Tag", { id => "tag" });
1820
1921 1;
20
4242 subtest 'testing m2m updates with IntrospectableM2M' => sub {
4343 ok $dvd_rs->result_class->can("_m2m_metadata"), "dvd rs has m2m metadata";
4444 my $dvd_item = $dvd_rs->first;
45 my $tag_ids = [$dvd_item->tags_rs->get_column('id')->all];
46
47 subtest 'add one' => sub {
48 push @$tag_ids, 1;
49
50 my %updates = (
51 dvd_id => $dvd_item->id,
52 tags => $tag_ids,
53 );
54
55 $dbic_trace->clear;
56
57 $dvd_rs->recursive_update(\%updates);
58
59 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
60 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
61 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 1, "update executed one insert";
62
63 is $dvd_item->tags_rs->count, 3, "DVD item has 3 tags";
64 };
65
66 subtest 'no changes' => sub {
67 $dbic_trace->clear;
68
69 my %updates = (
70 dvd_id => $dvd_item->id,
71 tags => $tag_ids,
72 );
73
74 $dvd_rs->recursive_update(\%updates);
75
76 is $dbic_trace->count_messages, 2, "two queries executed";
77 is $dbic_trace->count_messages("^SELECT"), 2, "update executed two select queries";
78
79 is $dvd_item->tags_rs->count, 3, "DVD item still has 3 tags";
80 };
81
82 subtest 'remove one' => sub {
83 shift @$tag_ids;
84
85 my %updates = (
86 dvd_id => $dvd_item->id,
87 tags => $tag_ids,
88 );
89
90 $dbic_trace->clear;
91
92 $dvd_rs->recursive_update(\%updates);
93
94 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
95 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
96 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
97
98 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
99 };
100
101 subtest 'add recursive' => sub {
102 #push @$tag_ids, ( 4, 5, 6 );
103
104 my %updates = (
105 dvd_id => $dvd_item->id,
106 tags => [
107 (map { { name => $_->name, id => $_->id } }
108 $dvd_item->tags->all),
109 { name => "winnie" },
110 { name => "fanny" },
111 { name => "sammy" },
112 ],
113 );
114
115 $dbic_trace->clear;
116
117 $dvd_rs->recursive_update(\%updates);
118
119 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
120 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
121 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 3, "update executed three inserts in dvdtag";
122 is $dbic_trace->count_messages("^INSERT INTO tag "), 3, "update executed three inserts in tag";
123
124 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
125 };
126
127 subtest 'update recursive' => sub {
128 #push @$tag_ids, ( 4, 5, 6 );
129
130 my %updates = (
131 dvd_id => $dvd_item->id,
132 tags => [(
133 map { { name => $_->name.'_Changed', id => $_->id } }
134 $dvd_item->tags->all
135 )],
136 );
137
138 $dbic_trace->clear;
139
140 $dvd_rs->recursive_update(\%updates);
141
142 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
143 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
144 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no inserts in dvdtag";
145 is $dbic_trace->count_messages("^UPDATE tag "), 5, "update executed five updates in tag";
146
147 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
148 };
149
150 subtest 'update and remove' => sub {
151 my %updates = (
152 dvd_id => $dvd_item->id,
153 tags => [(
154 map { { name => $_->name.'More', id => $_->id } }
155 $dvd_item->tags->all
156 )],
157 );
158
159 $updates{tags} = [splice @{$updates{tags}}, 2, 3];
160
161 $dbic_trace->clear;
162
163 $dvd_rs->recursive_update(\%updates);
164
165 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
166 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
167 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no inserts in dvdtag";
168 is $dbic_trace->count_messages("^UPDATE tag "), 3, "update executed three updates in tag";
169
170 is $dvd_item->tags_rs->count, 3, "DVD item has 3 tags";
171 };
172
173 subtest 'update and add' => sub {
174 my %updates = (
175 dvd_id => $dvd_item->id,
176 tags => [
177 (map { { name => $_->name.'More', id => $_->id } }
178 $dvd_item->tags->all),
179 { name => "rob" },
180 { name => "bot" },
181 ],
182 );
183
184
185 $dbic_trace->clear;
186
187 $dvd_rs->recursive_update(\%updates);
188
189 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
190 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
191 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed two inserts in dvdtag";
192 is $dbic_trace->count_messages("^UPDATE tag "), 3, "update executed three updates in tag";
193
194 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
195 };
196
197 subtest 'remove several' => sub {
198 my %updates = (
199 dvd_id => $dvd_item->id,
200 tags => [4,5],
201 );
202
203 $dbic_trace->clear;
204
205 $dvd_rs->recursive_update(\%updates);
206
207 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
208 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
209 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
210
211 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
212 };
213
214 subtest 'remove all' => sub {
215 my %updates = (
216 dvd_id => $dvd_item->id,
217 tags => [],
218 );
219
220 $dbic_trace->clear;
221
222 $dvd_rs->recursive_update(\%updates);
223
224 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
225 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
226
227 is $dvd_item->tags_rs->count, 0, "DVD item has no tags";
228 };
229
230 subtest 'old set_$rel behaviour' => sub {
231 my %updates = (
232 dvd_id => $dvd_item->id,
233 tags => [2,4],
234 );
235
236 $dbic_trace->clear;
237
238 $dvd_rs->recursive_update(\%updates, {m2m_force_set_rel => 1});
239
240 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
241 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed 2 insert";
242
243 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
244
245 # doing this two times to test identical behaviour
246 $dbic_trace->clear;
247
248 $dvd_rs->recursive_update(\%updates, {m2m_force_set_rel => 1});
249
250 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
251 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed 2 insert";
252
253 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
45
46 # wrap subtest in a transaction
47 $schema->txn_begin;
48
49 subtest 'relationship name = foreign key column name' => sub {
50 my $tag_ids = [$dvd_item->tags_rs->get_column('id')->all];
51 is_deeply([sort @$tag_ids], [2, 3], "dvd has tags 2 and 3");
52
53 subtest 'add one' => sub {
54 push @$tag_ids, 1;
55
56 my %updates = (
57 dvd_id => $dvd_item->id,
58 tags => $tag_ids,
59 );
60
61 $dbic_trace->clear;
62
63 $dvd_rs->recursive_update(\%updates);
64
65 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
66 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
67 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 1, "update executed one insert";
68
69 is $dvd_item->tags_rs->count, 3, "DVD item has 3 tags";
70 };
71
72 subtest 'no changes' => sub {
73 $dbic_trace->clear;
74
75 my %updates = (
76 dvd_id => $dvd_item->id,
77 tags => $tag_ids,
78 );
79
80 $dvd_rs->recursive_update(\%updates);
81
82 is $dbic_trace->count_messages, 2, "two queries executed";
83 is $dbic_trace->count_messages("^SELECT"), 2, "update executed two select queries";
84
85 is $dvd_item->tags_rs->count, 3, "DVD item still has 3 tags";
86 };
87
88 subtest 'remove one' => sub {
89 shift @$tag_ids;
90
91 my %updates = (
92 dvd_id => $dvd_item->id,
93 tags => $tag_ids,
94 );
95
96 $dbic_trace->clear;
97
98 $dvd_rs->recursive_update(\%updates);
99
100 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
101 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
102 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
103
104 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
105 };
106
107 subtest 'add recursive' => sub {
108 #push @$tag_ids, ( 4, 5, 6 );
109
110 my %updates = (
111 dvd_id => $dvd_item->id,
112 tags => [
113 (map { { name => $_->name, id => $_->id } }
114 $dvd_item->tags->all),
115 { name => "winnie" },
116 { name => "fanny" },
117 { name => "sammy" },
118 ],
119 );
120
121 $dbic_trace->clear;
122
123 $dvd_rs->recursive_update(\%updates);
124
125 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
126 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
127 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 3, "update executed three inserts in dvdtag";
128 is $dbic_trace->count_messages("^INSERT INTO tag "), 3, "update executed three inserts in tag";
129
130 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
131 };
132
133 subtest 'update recursive' => sub {
134 #push @$tag_ids, ( 4, 5, 6 );
135
136 my %updates = (
137 dvd_id => $dvd_item->id,
138 tags => [(
139 map { { name => $_->name.'_Changed', id => $_->id } }
140 $dvd_item->tags->all
141 )],
142 );
143
144 $dbic_trace->clear;
145
146 $dvd_rs->recursive_update(\%updates);
147
148 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
149 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
150 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no inserts in dvdtag";
151 is $dbic_trace->count_messages("^UPDATE tag "), 5, "update executed five updates in tag";
152
153 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
154 };
155
156 subtest 'update and remove' => sub {
157 my %updates = (
158 dvd_id => $dvd_item->id,
159 tags => [(
160 map { { name => $_->name.'More', id => $_->id } }
161 $dvd_item->tags->all
162 )],
163 );
164
165 $updates{tags} = [splice @{$updates{tags}}, 2, 3];
166
167 $dbic_trace->clear;
168
169 $dvd_rs->recursive_update(\%updates);
170
171 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
172 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
173 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no inserts in dvdtag";
174 is $dbic_trace->count_messages("^UPDATE tag "), 3, "update executed three updates in tag";
175
176 is $dvd_item->tags_rs->count, 3, "DVD item has 3 tags";
177 };
178
179 subtest 'update and add' => sub {
180 my %updates = (
181 dvd_id => $dvd_item->id,
182 tags => [
183 (map { { name => $_->name.'More', id => $_->id } }
184 $dvd_item->tags->all),
185 { name => "rob" },
186 { name => "bot" },
187 ],
188 );
189
190
191 $dbic_trace->clear;
192
193 $dvd_rs->recursive_update(\%updates);
194
195 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
196 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
197 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed two inserts in dvdtag";
198 is $dbic_trace->count_messages("^UPDATE tag "), 3, "update executed three updates in tag";
199
200 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
201 };
202
203 subtest 'remove several' => sub {
204 my %updates = (
205 dvd_id => $dvd_item->id,
206 tags => [4,5],
207 );
208
209 $dbic_trace->clear;
210
211 $dvd_rs->recursive_update(\%updates);
212
213 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
214 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
215 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
216
217 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
218 };
219
220 subtest 'remove all' => sub {
221 my %updates = (
222 dvd_id => $dvd_item->id,
223 tags => [],
224 );
225
226 $dbic_trace->clear;
227
228 $dvd_rs->recursive_update(\%updates);
229
230 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
231 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
232
233 is $dvd_item->tags_rs->count, 0, "DVD item has no tags";
234 };
235
236 subtest 'old set_$rel behaviour' => sub {
237 my %updates = (
238 dvd_id => $dvd_item->id,
239 tags => [2,4],
240 );
241
242 $dbic_trace->clear;
243
244 $dvd_rs->recursive_update(\%updates, {m2m_force_set_rel => 1});
245
246 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
247 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed 2 insert";
248
249 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
250
251 # doing this two times to test identical behaviour
252 $dbic_trace->clear;
253
254 $dvd_rs->recursive_update(\%updates, {m2m_force_set_rel => 1});
255
256 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
257 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed 2 insert";
258
259 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
260 };
261
262 # rollback all changes to keep the database in the same state it was
263 # at the beginning of the subtest
264 $schema->txn_rollback;
265 };
266
267 subtest 'relationship name != foreign key column name' => sub {
268 my $tag_ids = [$dvd_item->tags_rs->get_column('id')->all];
269 is_deeply([sort @$tag_ids], [2, 3], "dvd has tags 2 and 3");
270
271 # wrap subtest in a transaction
272 $schema->txn_begin;
273
274 subtest 'add one' => sub {
275 push @$tag_ids, 1;
276
277 my %updates = (
278 dvd_id => $dvd_item->id,
279 rel_tags => $tag_ids,
280 );
281
282 $dbic_trace->clear;
283
284 $dvd_rs->recursive_update(\%updates);
285
286 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
287 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
288 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 1, "update executed one insert";
289
290 is $dvd_item->tags_rs->count, 3, "DVD item has 3 tags";
291 };
292
293 subtest 'no changes' => sub {
294 $dbic_trace->clear;
295
296 my %updates = (
297 dvd_id => $dvd_item->id,
298 rel_tags => $tag_ids,
299 );
300
301 $dvd_rs->recursive_update(\%updates);
302
303 is $dbic_trace->count_messages, 2, "two queries executed";
304 is $dbic_trace->count_messages("^SELECT"), 2, "update executed two select queries";
305
306 is $dvd_item->tags_rs->count, 3, "DVD item still has 3 tags";
307 };
308
309 subtest 'remove one' => sub {
310 shift @$tag_ids;
311
312 my %updates = (
313 dvd_id => $dvd_item->id,
314 rel_tags => $tag_ids,
315 );
316
317 $dbic_trace->clear;
318
319 $dvd_rs->recursive_update(\%updates);
320
321 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
322 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
323 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
324
325 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
326 };
327
328 subtest 'add recursive' => sub {
329 #push @$tag_ids, ( 4, 5, 6 );
330
331 my %updates = (
332 dvd_id => $dvd_item->id,
333 rel_tags => [
334 (map { { name => $_->name, id => $_->id } }
335 $dvd_item->rel_tags->all),
336 { name => "winnie" },
337 { name => "fanny" },
338 { name => "sammy" },
339 ],
340 );
341
342 $dbic_trace->clear;
343
344 $dvd_rs->recursive_update(\%updates);
345
346 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
347 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
348 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 3, "update executed three inserts in dvdtag";
349 is $dbic_trace->count_messages("^INSERT INTO tag "), 3, "update executed three inserts in tag";
350
351 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
352 };
353
354 subtest 'update recursive' => sub {
355 #push @$tag_ids, ( 4, 5, 6 );
356
357 my %updates = (
358 dvd_id => $dvd_item->id,
359 rel_tags => [(
360 map { { name => $_->name.'_Changed', id => $_->id } }
361 $dvd_item->rel_tags->all
362 )],
363 );
364
365 $dbic_trace->clear;
366
367 $dvd_rs->recursive_update(\%updates);
368
369 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
370 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
371 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no inserts in dvdtag";
372 is $dbic_trace->count_messages("^UPDATE tag "), 5, "update executed five updates in tag";
373
374 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
375 };
376
377 subtest 'update and remove' => sub {
378 my %updates = (
379 dvd_id => $dvd_item->id,
380 rel_tags => [(
381 map { { name => $_->name.'More', id => $_->id } }
382 $dvd_item->rel_tags->all
383 )],
384 );
385
386 $updates{rel_tags} = [splice @{$updates{rel_tags}}, 2, 3];
387
388 $dbic_trace->clear;
389
390 $dvd_rs->recursive_update(\%updates);
391
392 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
393 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
394 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no inserts in dvdtag";
395 is $dbic_trace->count_messages("^UPDATE tag "), 3, "update executed three updates in tag";
396
397 is $dvd_item->tags_rs->count, 3, "DVD item has 3 tags";
398 };
399
400 subtest 'update and add' => sub {
401 my %updates = (
402 dvd_id => $dvd_item->id,
403 rel_tags => [
404 (map { { name => $_->name.'More', id => $_->id } }
405 $dvd_item->rel_tags->all),
406 { name => "rob" },
407 { name => "bot" },
408 ],
409 );
410
411
412 $dbic_trace->clear;
413
414 $dvd_rs->recursive_update(\%updates);
415
416 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
417 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 0, "update executed no delete";
418 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed two inserts in dvdtag";
419 is $dbic_trace->count_messages("^UPDATE tag "), 3, "update executed three updates in tag";
420
421 is $dvd_item->tags_rs->count, 5, "DVD item has 5 tags";
422 };
423
424 subtest 'remove several' => sub {
425 my %updates = (
426 dvd_id => $dvd_item->id,
427 rel_tags => [4,5],
428 );
429
430 $dbic_trace->clear;
431
432 $dvd_rs->recursive_update(\%updates);
433
434 ok ! $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did not remove all tags";
435 is $dbic_trace->count_messages("^DELETE FROM dvdtag "), 1, "update executed one delete";
436 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
437
438 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
439 };
440
441 subtest 'remove all' => sub {
442 my %updates = (
443 dvd_id => $dvd_item->id,
444 rel_tags => [],
445 );
446
447 $dbic_trace->clear;
448
449 $dvd_rs->recursive_update(\%updates);
450
451 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
452 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 0, "update executed no insert";
453
454 is $dvd_item->tags_rs->count, 0, "DVD item has no tags";
455 };
456
457 subtest 'old set_$rel behaviour' => sub {
458 my %updates = (
459 dvd_id => $dvd_item->id,
460 rel_tags => [2,4],
461 );
462
463 $dbic_trace->clear;
464
465 $dvd_rs->recursive_update(\%updates, {m2m_force_set_rel => 1});
466
467 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
468 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed 2 insert";
469
470 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
471
472 # doing this two times to test identical behaviour
473 $dbic_trace->clear;
474
475 $dvd_rs->recursive_update(\%updates, {m2m_force_set_rel => 1});
476
477 ok $dbic_trace->count_messages('^DELETE FROM dvdtag WHERE \( dvd = \? \)'), "update did remove all tags";
478 is $dbic_trace->count_messages("^INSERT INTO dvdtag "), 2, "update executed 2 insert";
479
480 is $dvd_item->tags_rs->count, 2, "DVD item has 2 tags";
481 };
482
483 # rollback all changes to keep the database in the same state it was
484 # at the beginning of the subtest
485 $schema->txn_rollback;
254486 };
255487 };
256488