Wrap dangerous Ordered operations in transactions (still needs optimisations wrt...
[dbsrgits/DBIx-Class.git] / t / 87ordered.t
CommitLineData
93cec8c3 1# vim: filetype=perl
70350518 2use strict;
3use warnings;
93cec8c3 4
70350518 5use Test::More;
6use lib qw(t/lib);
7use DBICTest;
93cec8c3 8
1d941d67 9use POSIX qw(ceil);
10
a47e1233 11my $schema = DBICTest->init_schema();
93cec8c3 12
97bfce50 13plan tests => 1269;
93cec8c3 14
70350518 15my $employees = $schema->resultset('Employee');
16$employees->delete();
169bb185 17
70350518 18foreach (1..5) {
19 $employees->create({ name=>'temp' });
20}
21$employees = $employees->search(undef,{order_by=>'position'});
22ok( check_rs($employees), "intial positions" );
b1c66eea 23
70350518 24hammer_rs( $employees );
169bb185 25
70350518 26DBICTest::Employee->grouping_column('group_id');
27$employees->delete();
79dc353a 28foreach my $group_id (1..4) {
70350518 29 foreach (1..6) {
30 $employees->create({ name=>'temp', group_id=>$group_id });
169bb185 31 }
70350518 32}
33$employees = $employees->search(undef,{order_by=>'group_id,position'});
169bb185 34
79dc353a 35foreach my $group_id (1..4) {
70350518 36 my $group_employees = $employees->search({group_id=>$group_id});
37 $group_employees->all();
38 ok( check_rs($group_employees), "group intial positions" );
39 hammer_rs( $group_employees );
169bb185 40}
41
79dc353a 42my $group_3 = $employees->search({group_id=>3});
43my $to_group = 1;
44my $to_pos = undef;
8f535707 45# now that we have transactions we need to work around stupid sqlite
46{
47 my @empl = $group_3->all;
48 while (my $employee = shift @empl) {
49 $employee->discard_changes; # since we are effective shift()ing the $rs while doing this
50 $employee->move_to_group($to_group, $to_pos);
51 $to_pos++;
52 $to_group = $to_group==1 ? 2 : 1;
53 }
79dc353a 54}
55foreach my $group_id (1..4) {
56 my $group_employees = $employees->search({group_id=>$group_id});
57 $group_employees->all();
58 ok( check_rs($group_employees), "group positions after move_to_group" );
59}
60
61my $employee = $employees->search({group_id=>4})->first;
62$employee->position(2);
63$employee->update;
64ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 1" );
65$employee = $employees->search({group_id=>4})->first;
66$employee->update({position=>3});
67ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 2" );
68$employee = $employees->search({group_id=>4})->first;
69$employee->group_id(1);
70$employee->update;
71ok(
72 check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
73 "overloaded update 3"
74);
75$employee = $employees->search({group_id=>4})->first;
76$employee->update({group_id=>2});
77ok(
78 check_rs($employees->search_rs({group_id=>2})) && check_rs($employees->search_rs({group_id=>4})),
79 "overloaded update 4"
80);
81$employee = $employees->search({group_id=>4})->first;
82$employee->group_id(1);
83$employee->position(3);
84$employee->update;
85ok(
86 check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
87 "overloaded update 5"
88);
89$employee = $employees->search({group_id=>4})->first;
90$employee->group_id(2);
91$employee->position(undef);
92$employee->update;
93ok(
94 check_rs($employees->search_rs({group_id=>2})) && check_rs($employees->search_rs({group_id=>4})),
95 "overloaded update 6"
96);
97$employee = $employees->search({group_id=>4})->first;
98$employee->update({group_id=>1,position=>undef});
99ok(
100 check_rs($employees->search_rs({group_id=>1})) && check_rs($employees->search_rs({group_id=>4})),
101 "overloaded update 7"
102);
103
1d941d67 104# multicol tests begin here
9beded8a 105DBICTest::Employee->grouping_column(['group_id_2', 'group_id_3']);
1d941d67 106$employees->delete();
9beded8a 107foreach my $group_id_2 (1..4) {
108 foreach my $group_id_3 (1..4) {
1d941d67 109 foreach (1..4) {
9beded8a 110 $employees->create({ name=>'temp', group_id_2=>$group_id_2, group_id_3=>$group_id_3 });
1d941d67 111 }
112 }
113}
9beded8a 114$employees = $employees->search(undef,{order_by=>[qw/group_id_2 group_id_3 position/]});
1d941d67 115
9beded8a 116foreach my $group_id_2 (1..3) {
117 foreach my $group_id_3 (1..3) {
118 my $group_employees = $employees->search({group_id_2=>$group_id_2, group_id_3=>$group_id_3});
1d941d67 119 $group_employees->all();
120 ok( check_rs($group_employees), "group intial positions" );
121 hammer_rs( $group_employees );
122 }
123}
124
125# move_to_group, specifying group by hash
9beded8a 126my $group_4 = $employees->search({group_id_2=>4});
1d941d67 127$to_group = 1;
128my $to_group_2_base = 7;
129my $to_group_2 = 1;
130$to_pos = undef;
8f535707 131
132# now that we have transactions we need to work around stupid sqlite
133{
134 my @empl = $group_3->all;
135 while (my $employee = shift @empl) {
136 $employee->move_to_group({group_id_2=>$to_group, group_id_3=>$to_group_2}, $to_pos);
137 $to_pos++;
1d941d67 138 $to_group = ($to_group % 3) + 1;
139 $to_group_2_base++;
140 $to_group_2 = (ceil($to_group_2_base/3.0) %3) +1
8f535707 141 }
1d941d67 142}
9beded8a 143foreach my $group_id_2 (1..4) {
144 foreach my $group_id_3 (1..4) {
145 my $group_employees = $employees->search({group_id_2=>$group_id_2,group_id_3=>$group_id_3});
1d941d67 146 $group_employees->all();
147 ok( check_rs($group_employees), "group positions after move_to_group" );
148 }
149}
150
151$employees->delete();
9beded8a 152foreach my $group_id_2 (1..4) {
153 foreach my $group_id_3 (1..4) {
1d941d67 154 foreach (1..4) {
9beded8a 155 $employees->create({ name=>'temp', group_id_2=>$group_id_2, group_id_3=>$group_id_3 });
1d941d67 156 }
157 }
158}
9beded8a 159$employees = $employees->search(undef,{order_by=>[qw/group_id_2 group_id_3 position/]});
1d941d67 160
9beded8a 161$employee = $employees->search({group_id_2=>4, group_id_3=>1})->first;
162$employee->group_id_2(1);
1d941d67 163$employee->update;
164ok(
9beded8a 165 check_rs($employees->search_rs({group_id_2=>4, group_id_3=>1}))
166 && check_rs($employees->search_rs({group_id_2=>1, group_id_3=>1})),
1d941d67 167 "overloaded multicol update 1"
168);
169
9beded8a 170$employee = $employees->search({group_id_2=>4, group_id_3=>1})->first;
171$employee->update({group_id_2=>2});
172ok( check_rs($employees->search_rs({group_id_2=>4, group_id_3=>1}))
173 && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>1})),
174 "overloaded multicol update 2"
1d941d67 175);
176
9beded8a 177$employee = $employees->search({group_id_2=>3, group_id_3=>1})->first;
178$employee->group_id_2(1);
179$employee->group_id_3(3);
1d941d67 180$employee->update();
9beded8a 181ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>1}))
182 && check_rs($employees->search_rs({group_id_2=>1, group_id_3=>3})),
1d941d67 183 "overloaded multicol update 3"
184);
185
9beded8a 186$employee = $employees->search({group_id_2=>3, group_id_3=>1})->first;
187$employee->update({group_id_2=>2, group_id_3=>3});
188ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>1}))
189 && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>3})),
1d941d67 190 "overloaded multicol update 4"
191);
192
9beded8a 193$employee = $employees->search({group_id_2=>3, group_id_3=>2})->first;
194$employee->update({group_id_2=>2, group_id_3=>4, position=>2});
195ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>2}))
196 && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>4})),
1d941d67 197 "overloaded multicol update 5"
198);
199
169bb185 200sub hammer_rs {
201 my $rs = shift;
707cbb2d 202 my $employee;
169bb185 203 my $count = $rs->count();
204 my $position_column = $rs->result_class->position_column();
58d387fe 205 my $row;
80010e2b 206
169bb185 207 foreach my $position (1..$count) {
80010e2b 208
dc66dea1 209 ($row) = $rs->search({ $position_column=>$position })->all();
169bb185 210 $row->move_previous();
211 ok( check_rs($rs), "move_previous( $position )" );
80010e2b 212
dc66dea1 213 ($row) = $rs->search({ $position_column=>$position })->all();
169bb185 214 $row->move_next();
215 ok( check_rs($rs), "move_next( $position )" );
80010e2b 216
dc66dea1 217 ($row) = $rs->search({ $position_column=>$position })->all();
169bb185 218 $row->move_first();
219 ok( check_rs($rs), "move_first( $position )" );
80010e2b 220
dc66dea1 221 ($row) = $rs->search({ $position_column=>$position })->all();
169bb185 222 $row->move_last();
223 ok( check_rs($rs), "move_last( $position )" );
80010e2b 224
169bb185 225 foreach my $to_position (1..$count) {
dc66dea1 226 ($row) = $rs->search({ $position_column=>$position })->all();
169bb185 227 $row->move_to($to_position);
228 ok( check_rs($rs), "move_to( $position => $to_position )" );
707cbb2d 229 }
80021def 230
97bfce50 231 $row = $rs->find({ position => $position });
707cbb2d 232 if ($position==1) {
169bb185 233 ok( !$row->previous_sibling(), 'no previous sibling' );
234 ok( !$row->first_sibling(), 'no first sibling' );
97bfce50 235 ok( $row->next_sibling->position > $position, 'next sibling position > than us');
236 is( $row->next_sibling->previous_sibling->position, $position, 'next-prev sibling is us');
237 ok( $row->last_sibling->position > $position, 'last sibling position > than us');
169bb185 238 }
239 else {
240 ok( $row->previous_sibling(), 'previous sibling' );
241 ok( $row->first_sibling(), 'first sibling' );
97bfce50 242 ok( $row->previous_sibling->position < $position, 'prev sibling position < than us');
243 is( $row->previous_sibling->next_sibling->position, $position, 'prev-next sibling is us');
244 ok( $row->first_sibling->position < $position, 'first sibling position < than us');
707cbb2d 245 }
169bb185 246 if ($position==$count) {
247 ok( !$row->next_sibling(), 'no next sibling' );
248 ok( !$row->last_sibling(), 'no last sibling' );
97bfce50 249 ok( $row->previous_sibling->position < $position, 'prev sibling position < than us');
250 is( $row->previous_sibling->next_sibling->position, $position, 'prev-next sibling is us');
251 ok( $row->first_sibling->position < $position, 'first sibling position < than us');
80021def 252 }
707cbb2d 253 else {
169bb185 254 ok( $row->next_sibling(), 'next sibling' );
255 ok( $row->last_sibling(), 'last sibling' );
97bfce50 256 ok( $row->next_sibling->position > $row->position, 'next sibling position > than us');
257 is( $row->next_sibling->previous_sibling->position, $position, 'next-prev sibling is us');
258 ok( $row->last_sibling->position > $row->position, 'last sibling position > than us');
707cbb2d 259 }
260
80010e2b 261 }
80010e2b 262}
263
169bb185 264sub check_rs {
265 my( $rs ) = @_;
266 $rs->reset();
267 my $position_column = $rs->result_class->position_column();
93cec8c3 268 my $expected_position = 0;
169bb185 269 while (my $row = $rs->next()) {
93cec8c3 270 $expected_position ++;
169bb185 271 if ($row->get_column($position_column)!=$expected_position) {
133dd22a 272 return 0;
80021def 273 }
93cec8c3 274 }
133dd22a 275 return 1;
93cec8c3 276}
277