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# multicol tests begin here 100DBICTest::Employee->grouping_column(['group_id_2', 'group_id_3']); 101$employees->delete(); 102foreach my $group_id_2 (1..4) { 103 foreach my $group_id_3 (1..4) { 104 foreach (1..4) { 105 $employees->create({ name=>'temp', group_id_2=>$group_id_2, group_id_3=>$group_id_3 }); 106 } 107 } 108} 109$employees = $employees->search(undef,{order_by=>[qw/group_id_2 group_id_3 position/]}); 110 111foreach my $group_id_2 (1..3) { 112 foreach my $group_id_3 (1..3) { 113 my $group_employees = $employees->search({group_id_2=>$group_id_2, group_id_3=>$group_id_3}); 114 $group_employees->all(); 115 ok( check_rs($group_employees), "group intial positions" ); 116 hammer_rs( $group_employees ); 117 } 118} 119 120# move_to_group, specifying group by hash 121my $group_4 = $employees->search({group_id_2=>4}); 122$to_group = 1; 123my $to_group_2_base = 7; 124my $to_group_2 = 1; 125$to_pos = undef; 126 127{ 128 my @empl = $group_3->all; 129 while (my $employee = shift @empl) { 130 $employee->move_to_group({group_id_2=>$to_group, group_id_3=>$to_group_2}, $to_pos); 131 $to_pos++; 132 $to_group = ($to_group % 3) + 1; 133 $to_group_2_base++; 134 $to_group_2 = (ceil($to_group_2_base/3.0) %3) +1 135 } 136} 137foreach my $group_id_2 (1..4) { 138 foreach my $group_id_3 (1..4) { 139 my $group_employees = $employees->search({group_id_2=>$group_id_2,group_id_3=>$group_id_3}); 140 ok( check_rs($group_employees), "group positions after move_to_group" ); 141 } 142} 143 144$employees->delete(); 145foreach my $group_id_2 (1..4) { 146 foreach my $group_id_3 (1..4) { 147 foreach (1..4) { 148 $employees->create({ name=>'temp', group_id_2=>$group_id_2, group_id_3=>$group_id_3 }); 149 } 150 } 151} 152$employees = $employees->search(undef,{order_by=>[qw/group_id_2 group_id_3 position/]}); 153 154$employee = $employees->search({group_id_2=>4, group_id_3=>1})->first; 155$employee->group_id_2(1); 156$employee->update; 157ok( 158 check_rs($employees->search_rs({group_id_2=>4, group_id_3=>1})) 159 && check_rs($employees->search_rs({group_id_2=>1, group_id_3=>1})), 160 "overloaded multicol update 1" 161); 162 163$employee = $employees->search({group_id_2=>4, group_id_3=>1})->first; 164$employee->update({group_id_2=>2}); 165ok( check_rs($employees->search_rs({group_id_2=>4, group_id_3=>1})) 166 && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>1})), 167 "overloaded multicol update 2" 168); 169 170$employee = $employees->search({group_id_2=>3, group_id_3=>1})->first; 171$employee->group_id_2(1); 172$employee->group_id_3(3); 173$employee->update(); 174ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>1})) 175 && check_rs($employees->search_rs({group_id_2=>1, group_id_3=>3})), 176 "overloaded multicol update 3" 177); 178 179$employee = $employees->search({group_id_2=>3, group_id_3=>1})->first; 180$employee->update({group_id_2=>2, group_id_3=>3}); 181ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>1})) 182 && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>3})), 183 "overloaded multicol update 4" 184); 185 186$employee = $employees->search({group_id_2=>3, group_id_3=>2})->first; 187$employee->update({group_id_2=>2, group_id_3=>4, position=>2}); 188ok( check_rs($employees->search_rs({group_id_2=>3, group_id_3=>2})) 189 && check_rs($employees->search_rs({group_id_2=>2, group_id_3=>4})), 190 "overloaded multicol update 5" 191); 192 193sub hammer_rs { 194 my $rs = shift; 195 my $employee; 196 my $count = $rs->count(); 197 my $position_column = $rs->result_class->position_column(); 198 my $row; 199 200 foreach my $position (1..$count) { 201 202 ($row) = $rs->search({ $position_column=>$position })->all(); 203 $row->move_previous(); 204 ok( check_rs($rs), "move_previous( $position )" ); 205 206 ($row) = $rs->search({ $position_column=>$position })->all(); 207 $row->move_next(); 208 ok( check_rs($rs), "move_next( $position )" ); 209 210 ($row) = $rs->search({ $position_column=>$position })->all(); 211 $row->move_first(); 212 ok( check_rs($rs), "move_first( $position )" ); 213 214 ($row) = $rs->search({ $position_column=>$position })->all(); 215 $row->move_last(); 216 ok( check_rs($rs), "move_last( $position )" ); 217 218 foreach my $to_position (1..$count) { 219 ($row) = $rs->search({ $position_column=>$position })->all(); 220 $row->move_to($to_position); 221 ok( check_rs($rs), "move_to( $position => $to_position )" ); 222 } 223 224 $row = $rs->find({ position => $position }); 225 if ($position==1) { 226 ok( !$row->previous_sibling(), 'no previous sibling' ); 227 ok( !$row->first_sibling(), 'no first sibling' ); 228 ok( $row->next_sibling->position > $position, 'next sibling position > than us'); 229 is( $row->next_sibling->previous_sibling->position, $position, 'next-prev sibling is us'); 230 ok( $row->last_sibling->position > $position, 'last sibling position > than us'); 231 } 232 else { 233 ok( $row->previous_sibling(), 'previous sibling' ); 234 ok( $row->first_sibling(), 'first sibling' ); 235 ok( $row->previous_sibling->position < $position, 'prev sibling position < than us'); 236 is( $row->previous_sibling->next_sibling->position, $position, 'prev-next sibling is us'); 237 ok( $row->first_sibling->position < $position, 'first sibling position < than us'); 238 } 239 if ($position==$count) { 240 ok( !$row->next_sibling(), 'no next sibling' ); 241 ok( !$row->last_sibling(), 'no last sibling' ); 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'); 245 } 246 else { 247 ok( $row->next_sibling(), 'next sibling' ); 248 ok( $row->last_sibling(), 'last sibling' ); 249 ok( $row->next_sibling->position > $row->position, 'next sibling position > than us'); 250 is( $row->next_sibling->previous_sibling->position, $position, 'next-prev sibling is us'); 251 ok( $row->last_sibling->position > $row->position, 'last sibling position > than us'); 252 } 253 254 } 255} 256 257sub check_rs { 258 my( $rs ) = @_; 259 $rs->reset(); 260 my $position_column = $rs->result_class->position_column(); 261 my $expected_position = 0; 262 while (my $row = $rs->next()) { 263 $expected_position ++; 264 if ($row->get_column($position_column)!=$expected_position) { 265 return 0; 266 } 267 } 268 return 1; 269} 270 271done_testing; 272