Codebase list libdbix-class-perl / 5da5cf2
Fix another ::FilterColumn bug sigh... ( cherry-pick of b482a0958 ) This one is technically a regression introduced by dc6dadae, which aimed to solve multiple runs on already-dirty columns. Unfortunately this very same change broke update(). Overload get_dirty_columns to fix that, and add a bunch of tests validating nothing crazy is going on. I should have seen all of these problems when FC was initially considered, but alas I was too damn inexperienced :/ Peter Rabbitson 7 years ago
4 changed file(s) with 101 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
00 Revision history for DBIx::Class
11
22 * Fixes
3 - Another relatively invasive set of ::FilterColumn changes, covering
4 potential data loss (RT#111567). Please run your regression tests!
35 - Fix use of ::Schema::Versioned combined with a user-supplied
46 $dbh->{HandleError} (GH#101)
57 - Fix parsing of DSNs containing driver arguments (GH#99)
7777 sub get_column {
7878 my ($self, $col) = @_;
7979
80 if (exists $self->{_filtered_column}{$col}) {
81 return $self->{_column_data}{$col} ||= $self->_column_to_storage (
82 $col, $self->{_filtered_column}{$col}
83 );
84 }
80 ! exists $self->{_column_data}{$col}
81 and
82 exists $self->{_filtered_column}{$col}
83 and
84 $self->{_column_data}{$col} = $self->_column_to_storage (
85 $col, $self->{_filtered_column}{$col}
86 );
8587
8688 return $self->next::method ($col);
8789 }
98100 ;
99101
100102 $self->next::method (@_);
103 }
104
105 # and *another* separate codepath, argh!
106 sub get_dirty_columns {
107 my $self = shift;
108
109 $self->{_dirty_columns}{$_}
110 and
111 ! exists $self->{_column_data}{$_}
112 and
113 $self->{_column_data}{$_} = $self->_column_to_storage (
114 $_, $self->{_filtered_column}{$_}
115 )
116 for keys %{$self->{_filtered_column}||{}};
117
118 $self->next::method(@_);
101119 }
102120
103121 sub store_column {
129129 is $from_storage_ran, ++$expected_from, 'from did run';
130130 is $to_storage_ran, $expected_to, 'to did not run';
131131
132 ok ! $artist->is_changed, 'object clean';
133 is_deeply
134 { $artist->get_dirty_columns },
135 {},
136 'dirty columns as expected',
137 ;
138
139 is $from_storage_ran, $expected_from, 'from did not run';
140 is $to_storage_ran, $expected_to, 'to did not run';
141
142 $artist->charfield(42);
143
144 is $from_storage_ran, $expected_from, 'from did not run';
145 is $to_storage_ran, ++$expected_to, 'to ran once, determining dirtyness';
146
147 is $artist->charfield, 42, 'setting once works';
148 ok $artist->is_column_changed('charfield'), 'column changed';
149 ok $artist->is_changed, 'object changed';
150 is_deeply
151 { $artist->get_dirty_columns },
152 { charfield => 21 },
153 'dirty columns as expected',
154 ;
155
156 is $from_storage_ran, $expected_from, 'from did not run';
157 is $to_storage_ran, $expected_to, 'to did not run';
158
159 $artist->charfield(66);
160 is $artist->charfield, 66, 'setting twice works';
161 ok $artist->is_column_changed('charfield'), 'column changed';
162 ok $artist->is_changed, 'object changed';
163
164 is $from_storage_ran, $expected_from, 'from did not run';
165 is $to_storage_ran, $expected_to, 'to did not run a second time on dirty column';
166
167 is_deeply
168 { $artist->get_dirty_columns },
169 { charfield => 33 },
170 'dirty columns as expected',
171 ;
172 is $from_storage_ran, $expected_from, 'from did not run';
173 is $to_storage_ran, ++$expected_to, 'to did run producing a new dirty_columns set';
174
175 is_deeply
176 { $artist->get_dirty_columns },
177 { charfield => 33 },
178 'dirty columns still as expected',
179 ;
180 is $from_storage_ran, $expected_from, 'from did not run';
181 is $to_storage_ran, $expected_to, 'to did not run on re-invoked get_dirty_columns';
182
183 $artist->update;
184 is $artist->charfield, 66, 'value still there';
185
186 is $from_storage_ran, $expected_from, 'from did not run';
187 is $to_storage_ran, $expected_to, 'to did not run ';
188
189 $artist->discard_changes;
190
191 is $from_storage_ran, $expected_from, 'from did not run after discard_changes';
192 is $to_storage_ran, $expected_to, 'to did not run after discard_changes';
193
194 is $artist->charfield, 66, 'value still there post reload';
195
196 is $from_storage_ran, ++$expected_from, 'from did run';
197 is $to_storage_ran, $expected_to, 'to did not run';
132198 }
133199
134200 # test in-memory operations
136202 sub { $schema->resultset('Artist')->new({ charfield => 42 }) },
137203 sub { my $art = $schema->resultset('Artist')->new({}); $art->charfield(42); $art },
138204 ) {
205 $schema->resultset('Artist')->delete;
139206
140207 my $expected_from = $from_storage_ran;
141208 my $expected_to = $to_storage_ran;
149216 ok( $artist->has_column_loaded('charfield'), 'Filtered column marked as loaded under new' );
150217 is( $artist->charfield, 42, 'Proper unfiltered value' );
151218 is( $artist->get_column('charfield'), 21, 'Proper filtered value' );
219
220 $artist->insert;
221 ($raw_db_charfield) = $schema->resultset('Artist')
222 ->search ($artist->ident_condition)
223 ->get_column('charfield')
224 ->next;
225
226 is $raw_db_charfield, 21, 'Proper value in database';
152227 }
153228
154229 # test literals
5656 store_column
5757 get_column
5858 get_columns
59 get_dirty_columns
5960 has_column_loaded
6061 /],
6162 },