Merge 'trunk' into 'replication_dedux'
[dbsrgits/DBIx-Class.git] / t / 87ordered.t
1 # vim: filetype=perl
2 use strict;
3 use warnings;  
4
5 use Test::More;
6 use lib qw(t/lib);
7 use DBICTest;
8
9 use POSIX qw(ceil);
10
11 my $schema = DBICTest->init_schema();
12
13 plan tests => 879;
14
15 my $employees = $schema->resultset('Employee');
16 $employees->delete();
17
18 foreach (1..5) {
19     $employees->create({ name=>'temp' });
20 }
21 $employees = $employees->search(undef,{order_by=>'position'});
22 ok( check_rs($employees), "intial positions" );
23
24 hammer_rs( $employees );
25
26 DBICTest::Employee->grouping_column('group_id');
27 $employees->delete();
28 foreach my $group_id (1..4) {
29     foreach (1..6) {
30         $employees->create({ name=>'temp', group_id=>$group_id });
31     }
32 }
33 $employees = $employees->search(undef,{order_by=>'group_id,position'});
34
35 foreach my $group_id (1..4) {
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 );
40 }
41
42 my $group_3 = $employees->search({group_id=>3});
43 my $to_group = 1;
44 my $to_pos = undef;
45 while (my $employee = $group_3->next) {
46         $employee->move_to_group($to_group, $to_pos);
47         $to_pos++;
48         $to_group = $to_group==1 ? 2 : 1;
49 }
50 foreach my $group_id (1..4) {
51     my $group_employees = $employees->search({group_id=>$group_id});
52     $group_employees->all();
53     ok( check_rs($group_employees), "group positions after move_to_group" );
54 }
55
56 my $employee = $employees->search({group_id=>4})->first;
57 $employee->position(2);
58 $employee->update;
59 ok( check_rs($employees->search_rs({group_id=>4})), "overloaded update 1" );
60 $employee = $employees->search({group_id=>4})->first;
61 $employee->update({position=>3});
62 ok( 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;
66 ok(
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});
72 ok(
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;
80 ok(
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;
88 ok(
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});
94 ok(
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
100 DBICTest::Employee->grouping_column(['group_id', 'group_id_2']);
101 $employees->delete();
102 foreach my $group_id (1..4) {
103     foreach my $group_id_2 (1..4) {
104         foreach (1..4) {
105             $employees->create({ name=>'temp', group_id=>$group_id, group_id_2=>$group_id_2 });
106         }
107     }
108 }
109 $employees = $employees->search(undef,{order_by=>'group_id,group_id_2,position'});
110
111 foreach my $group_id (1..3) {
112     foreach my $group_id_2 (1..3) {
113         my $group_employees = $employees->search({group_id=>$group_id, group_id_2=>$group_id_2});
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
121 my $group_4 = $employees->search({group_id=>4});
122 $to_group = 1;
123 my $to_group_2_base = 7;
124 my $to_group_2 = 1;
125 $to_pos = undef;
126 while (my $employee = $group_4->next) {
127         $employee->move_to_group({group_id=>$to_group, group_id_2=>$to_group_2}, $to_pos);
128         $to_pos++;
129     $to_group = ($to_group % 3) + 1;
130     $to_group_2_base++;
131     $to_group_2 = (ceil($to_group_2_base/3.0) %3) +1
132 }
133 foreach my $group_id (1..4) {
134     foreach my $group_id_2 (1..4) {
135         my $group_employees = $employees->search({group_id=>$group_id,group_id_2=>$group_id_2});
136         $group_employees->all();
137         ok( check_rs($group_employees), "group positions after move_to_group" );
138     }
139 }
140
141 $employees->delete();
142 foreach my $group_id (1..4) {
143     foreach my $group_id_2 (1..4) {
144         foreach (1..4) {
145             $employees->create({ name=>'temp', group_id=>$group_id, group_id_2=>$group_id_2 });
146         }
147     }
148 }
149 $employees = $employees->search(undef,{order_by=>'group_id,group_id_2,position'});
150
151 $employee = $employees->search({group_id=>4, group_id_2=>1})->first;
152 $employee->group_id(1);
153 $employee->update;
154 ok( 
155     check_rs($employees->search_rs({group_id=>4, group_id_2=>1}))
156     && check_rs($employees->search_rs({group_id=>1, group_id_2=>1})), 
157     "overloaded multicol update 1" 
158 );
159
160 $employee = $employees->search({group_id=>4, group_id_2=>1})->first;
161 $employee->update({group_id=>2});
162 ok( check_rs($employees->search_rs({group_id=>4, group_id_2=>1}))
163     && check_rs($employees->search_rs({group_id=>2, group_id_2=>1})), 
164     "overloaded multicol update 2" 
165 );
166
167 $employee = $employees->search({group_id=>3, group_id_2=>1})->first;
168 $employee->group_id(1);
169 $employee->group_id_2(3);
170 $employee->update();
171 ok( check_rs($employees->search_rs({group_id=>3, group_id_2=>1}))
172     && check_rs($employees->search_rs({group_id=>1, group_id_2=>3})),
173     "overloaded multicol update 3" 
174 );
175
176 $employee = $employees->search({group_id=>3, group_id_2=>1})->first;
177 $employee->update({group_id=>2, group_id_2=>3});
178 ok( check_rs($employees->search_rs({group_id=>3, group_id_2=>1}))
179     && check_rs($employees->search_rs({group_id=>2, group_id_2=>3})), 
180     "overloaded multicol update 4" 
181 );
182
183 $employee = $employees->search({group_id=>3, group_id_2=>2})->first;
184 $employee->update({group_id=>2, group_id_2=>4, position=>2});
185 ok( check_rs($employees->search_rs({group_id=>3, group_id_2=>2}))
186     && check_rs($employees->search_rs({group_id=>2, group_id_2=>4})), 
187     "overloaded multicol update 5" 
188 );
189
190 sub hammer_rs {
191     my $rs = shift;
192     my $employee;
193     my $count = $rs->count();
194     my $position_column = $rs->result_class->position_column();
195     my $row;
196
197     foreach my $position (1..$count) {
198
199         ($row) = $rs->search({ $position_column=>$position })->all();
200         $row->move_previous();
201         ok( check_rs($rs), "move_previous( $position )" );
202
203         ($row) = $rs->search({ $position_column=>$position })->all();
204         $row->move_next();
205         ok( check_rs($rs), "move_next( $position )" );
206
207         ($row) = $rs->search({ $position_column=>$position })->all();
208         $row->move_first();
209         ok( check_rs($rs), "move_first( $position )" );
210
211         ($row) = $rs->search({ $position_column=>$position })->all();
212         $row->move_last();
213         ok( check_rs($rs), "move_last( $position )" );
214
215         foreach my $to_position (1..$count) {
216             ($row) = $rs->search({ $position_column=>$position })->all();
217             $row->move_to($to_position);
218             ok( check_rs($rs), "move_to( $position => $to_position )" );
219         }
220
221         ($row) = $rs->search({ position=>$position })->all();
222         if ($position==1) {
223             ok( !$row->previous_sibling(), 'no previous sibling' );
224             ok( !$row->first_sibling(), 'no first sibling' );
225         }
226         else {
227             ok( $row->previous_sibling(), 'previous sibling' );
228             ok( $row->first_sibling(), 'first sibling' );
229         }
230         if ($position==$count) {
231             ok( !$row->next_sibling(), 'no next sibling' );
232             ok( !$row->last_sibling(), 'no last sibling' );
233         }
234         else {
235             ok( $row->next_sibling(), 'next sibling' );
236             ok( $row->last_sibling(), 'last sibling' );
237         }
238
239     }
240 }
241
242 sub check_rs {
243     my( $rs ) = @_;
244     $rs->reset();
245     my $position_column = $rs->result_class->position_column();
246     my $expected_position = 0;
247     while (my $row = $rs->next()) {
248         $expected_position ++;
249         if ($row->get_column($position_column)!=$expected_position) {
250             return 0;
251         }
252     }
253     return 1;
254 }
255