1 BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
11 my $from_storage_ran = 0;
12 my $to_storage_ran = 0;
13 my $schema = DBICTest->init_schema( no_populate => 1 );
14 DBICTest::Schema::Artist->load_components(qw(FilterColumn InflateColumn));
15 DBICTest::Schema::Artist->filter_column(charfield => {
16 filter_from_storage => sub { $from_storage_ran++; defined $_[1] ? $_[1] * 2 : undef },
17 filter_to_storage => sub { $to_storage_ran++; defined $_[1] ? $_[1] / 2 : undef },
19 Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
21 my $artist = $schema->resultset('Artist')->create( { charfield => 20 } );
23 # this should be using the cursor directly, no inflation/processing of any sort
24 my ($raw_db_charfield) = $schema->resultset('Artist')
25 ->search ($artist->ident_condition)
26 ->get_column('charfield')
31 is ($raw_db_charfield, 10, 'INSERT: correctly unfiltered on insertion');
33 for my $reloaded (0, 1) {
34 my $test = $reloaded ? 'reloaded' : 'stored';
35 $artist->discard_changes if $reloaded;
37 is( $artist->charfield , 20, "got $test filtered charfield" );
41 $artist->discard_changes;
42 is( $artist->charfield , 20, "got filtered charfield" );
44 $artist->update ({ charfield => 40 });
45 ($raw_db_charfield) = $schema->resultset('Artist')
46 ->search ($artist->ident_condition)
47 ->get_column('charfield')
51 is ($raw_db_charfield, 20, 'UPDATE: correctly unflitered on update');
53 $artist->discard_changes;
54 $artist->charfield(40);
55 ok( !$artist->is_column_changed('charfield'), 'column is not dirty after setting the same value' );
58 my $cd = $schema->resultset('CD')->create({
59 artist => { charfield => 20 },
60 title => 'fun time city!',
61 year => 'forevertime',
63 ($raw_db_charfield) = $schema->resultset('Artist')
64 ->search ($cd->artist->ident_condition)
65 ->get_column('charfield')
70 is $raw_db_charfield, 10, 'artist charfield gets correctly unfiltered w/ MC';
71 is $cd->artist->charfield, 20, 'artist charfield gets correctly filtered w/ MC';
75 my $expected_from = $from_storage_ran;
76 my $expected_to = $to_storage_ran;
78 # ensure we are creating a fresh obj
79 $artist = $schema->resultset('Artist')->single($artist->ident_condition);
81 is $from_storage_ran, $expected_from, 'from has not run yet';
82 is $to_storage_ran, $expected_to, 'to has not run yet';
86 $artist->get_filtered_column('charfield'),
88 $artist->get_column('charfield'),
89 'filter/unfilter differ'
91 is $from_storage_ran, ++$expected_from, 'from ran once, therefor caches';
92 is $to_storage_ran, $expected_to, 'to did not run';
94 $artist->charfield(6);
95 is $from_storage_ran, $expected_from, 'from did not run';
96 is $to_storage_ran, ++$expected_to, 'to ran once';
98 ok ($artist->is_column_changed ('charfield'), 'Column marked as dirty');
101 is $from_storage_ran, $expected_from, 'from did not run';
102 is $to_storage_ran, $expected_to, 'to did not run';
106 $artist->set_column(charfield => 3);
107 ok (! $artist->is_column_changed ('charfield'), 'Column not marked as dirty on same set_column value');
108 is ($artist->charfield, '6', 'Column set properly (cache blown)');
109 is $from_storage_ran, ++$expected_from, 'from ran once (set_column blew cache)';
110 is $to_storage_ran, $expected_to, 'to did not run';
112 $artist->charfield(6);
113 ok (! $artist->is_column_changed ('charfield'), 'Column not marked as dirty on same accessor-set value');
114 is ($artist->charfield, '6', 'Column set properly');
115 is $from_storage_ran, $expected_from, 'from did not run';
116 is $to_storage_ran, ++$expected_to, 'to did run once (call in to set_column)';
118 $artist->store_column(charfield => 4);
119 ok (! $artist->is_column_changed ('charfield'), 'Column not marked as dirty on differing store_column value');
120 is ($artist->charfield, '8', 'Cache properly blown');
121 is $from_storage_ran, ++$expected_from, 'from did not run';
122 is $to_storage_ran, $expected_to, 'to did not run';
124 $artist->update({ charfield => undef });
125 is $from_storage_ran, $expected_from, 'from did not run';
126 is $to_storage_ran, ++$expected_to, 'to did run';
128 $artist->discard_changes;
129 is ( $artist->get_column('charfield'), undef, 'Got back null' );
130 is ( $artist->charfield, undef, 'Got back null through filter' );
132 is $from_storage_ran, ++$expected_from, 'from did run';
133 is $to_storage_ran, $expected_to, 'to did not run';
137 # test in-memory operations
138 for my $artist_maker (
139 sub { $schema->resultset('Artist')->new({ charfield => 42 }) },
140 sub { my $art = $schema->resultset('Artist')->new({}); $art->charfield(42); $art },
143 my $expected_from = $from_storage_ran;
144 my $expected_to = $to_storage_ran;
146 my $artist = $artist_maker->();
148 is $from_storage_ran, $expected_from, 'from has not run yet';
149 is $to_storage_ran, $expected_to, 'to has not run yet';
151 ok( ! $artist->has_column_loaded('artistid'), 'pk not loaded' );
152 ok( $artist->has_column_loaded('charfield'), 'Filtered column marked as loaded under new' );
153 is( $artist->charfield, 42, 'Proper unfiltered value' );
154 is( $artist->get_column('charfield'), 21, 'Proper filtered value' );
158 for my $v ( \ '16', \[ '?', '16' ] ) {
159 my $rs = $schema->resultset('Artist');
162 my $art = $rs->new({ charfield => 10 });
165 is_deeply( $art->charfield, $v);
166 is_deeply( $art->get_filtered_column("charfield"), $v);
167 is_deeply( $art->get_column("charfield"), $v);
170 $art->discard_changes;
172 is ($art->get_column("charfield"), 16, "Literal inserted into database properly");
173 is ($art->charfield, 32, "filtering still works");
175 $art->update({ charfield => $v });
177 is_deeply( $art->charfield, $v);
178 is_deeply( $art->get_filtered_column("charfield"), $v);
179 is_deeply( $art->get_column("charfield"), $v);
181 $art->discard_changes;
183 is ($art->get_column("charfield"), 16, "Literal inserted into database properly");
184 is ($art->charfield, 32, "filtering still works");
189 DBICTest::Schema::Artist->inflate_column(charfield =>
190 { inflate => sub {}, deflate => sub {} }
192 } qr/InflateColumn can not be used on a column with a declared FilterColumn filter/, q(Can't inflate column after filter column);
194 DBICTest::Schema::Artist->inflate_column(name =>
195 { inflate => sub {}, deflate => sub {} }
199 DBICTest::Schema::Artist->filter_column(name => {
200 filter_to_storage => sub {},
201 filter_from_storage => sub {}
203 } qr/FilterColumn can not be used on a column with a declared InflateColumn inflator/, q(Can't filter column after inflate column);
206 # test when we do not set both filter_from_storage/filter_to_storage
207 DBICTest::Schema::Artist->filter_column(charfield => {
208 filter_to_storage => sub { $to_storage_ran++; $_[1] },
210 Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
212 ASYMMETRIC_TO_TEST: {
214 $artist->charfield(20);
217 my $expected_from = $from_storage_ran;
218 my $expected_to = $to_storage_ran;
220 $artist->charfield(10);
221 ok ($artist->is_column_changed ('charfield'), 'Column marked as dirty on accessor-set value');
222 is ($artist->charfield, '10', 'Column set properly');
223 is $from_storage_ran, $expected_from, 'from did not run';
224 is $to_storage_ran, ++$expected_to, 'to did run';
226 $artist->discard_changes;
228 is ($artist->charfield, '20', 'Column set properly');
229 is $from_storage_ran, $expected_from, 'from did not run';
230 is $to_storage_ran, $expected_to, 'to did not run';
233 DBICTest::Schema::Artist->filter_column(charfield => {
234 filter_from_storage => sub { $from_storage_ran++; $_[1] },
236 Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
238 ASYMMETRIC_FROM_TEST: {
240 $artist->charfield(23);
243 my $expected_from = $from_storage_ran;
244 my $expected_to = $to_storage_ran;
246 $artist->charfield(13);
247 ok ($artist->is_column_changed ('charfield'), 'Column marked as dirty on accessor-set value');
248 is ($artist->charfield, '13', 'Column set properly');
249 is $from_storage_ran, $expected_from, 'from did not run';
250 is $to_storage_ran, $expected_to, 'to did not run';
252 $artist->discard_changes;
254 is ($artist->charfield, '23', 'Column set properly');
255 is $from_storage_ran, ++$expected_from, 'from did run';
256 is $to_storage_ran, $expected_to, 'to did not run';
259 throws_ok { DBICTest::Schema::Artist->filter_column( charfield => {} ) }
260 qr/\QAn invocation of filter_column() must specify either a filter_from_storage or filter_to_storage/,
261 'Correctly throws exception for empty attributes'
265 # there are cases in the wild that autovivify stuff deep in the
266 # colinfo guts. While this is insane, there is no alternative
267 # so at leats make sure it keeps working...
269 $schema->source('Artist')->column_info('artistid')->{_filter_info} ||= {};
271 for my $key ('', 'primary') {
273 $schema->resultset('Artist')->find_or_create({ artistid => 42 }, { $key ? ( key => $key ) : () });
278 DBICTest::Schema::Artist->filter_column(artistid => {
279 filter_to_storage => sub { $_[1] * 100 },
280 filter_from_storage => sub { $_[1] - 100 },
283 for my $key ('', 'primary') {
285 $schema->resultset('Artist')->find_or_create({ artistid => 42 }, { $key ? ( key => $key ) : () });
286 } qr/\QUnable to satisfy requested constraint 'primary', FilterColumn values not usable for column(s): 'artistid'/;