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