update requirements
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / Base.pm
CommitLineData
996be9ee 1package DBIx::Class::Schema::Loader::Base;
2
3use strict;
4use warnings;
5use base qw/Class::Accessor::Fast/;
6use Class::C3;
fa994d3c 7use Carp::Clan qw/^DBIx::Class/;
996be9ee 8use UNIVERSAL::require;
9use DBIx::Class::Schema::Loader::RelBuilder;
10use Data::Dump qw/ dump /;
11use POSIX qw//;
dd03ee1a 12use File::Spec qw//;
419a2eeb 13use Cwd qw//;
7cab3ab7 14use Digest::MD5 qw//;
996be9ee 15require DBIx::Class;
16
32f784fc 17our $VERSION = '0.03999_01';
18
996be9ee 19__PACKAGE__->mk_ro_accessors(qw/
20 schema
21 schema_class
22
23 exclude
24 constraint
25 additional_classes
26 additional_base_classes
27 left_base_classes
28 components
29 resultset_components
59cfa251 30 skip_relationships
996be9ee 31 moniker_map
32 inflect_singular
33 inflect_plural
34 debug
35 dump_directory
d65cda9e 36 dump_overwrite
996be9ee 37
996be9ee 38 db_schema
39 _tables
40 classes
41 monikers
42 /);
43
44=head1 NAME
45
46DBIx::Class::Schema::Loader::Base - Base DBIx::Class::Schema::Loader Implementation.
47
48=head1 SYNOPSIS
49
50See L<DBIx::Class::Schema::Loader>
51
52=head1 DESCRIPTION
53
54This is the base class for the storage-specific C<DBIx::Class::Schema::*>
55classes, and implements the common functionality between them.
56
57=head1 CONSTRUCTOR OPTIONS
58
59These constructor options are the base options for
60L<DBIx::Class::Schema::Loader/loader_opts>. Available constructor options are:
61
59cfa251 62=head2 skip_relationships
996be9ee 63
59cfa251 64Skip setting up relationships. The default is to attempt the loading
65of relationships.
996be9ee 66
67=head2 debug
68
69If set to true, each constructive L<DBIx::Class> statement the loader
70decides to execute will be C<warn>-ed before execution.
71
d65cda9e 72=head2 db_schema
73
74Set the name of the schema to load (schema in the sense that your database
75vendor means it). Does not currently support loading more than one schema
76name.
77
996be9ee 78=head2 constraint
79
80Only load tables matching regex. Best specified as a qr// regex.
81
82=head2 exclude
83
84Exclude tables matching regex. Best specified as a qr// regex.
85
86=head2 moniker_map
87
8f9d7ce5 88Overrides the default table name to moniker translation. Can be either
89a hashref of table keys and moniker values, or a coderef for a translator
996be9ee 90function taking a single scalar table name argument and returning
91a scalar moniker. If the hash entry does not exist, or the function
92returns a false value, the code falls back to default behavior
93for that table name.
94
95The default behavior is: C<join '', map ucfirst, split /[\W_]+/, lc $table>,
96which is to say: lowercase everything, split up the table name into chunks
97anywhere a non-alpha-numeric character occurs, change the case of first letter
98of each chunk to upper case, and put the chunks back together. Examples:
99
100 Table Name | Moniker Name
101 ---------------------------
102 luser | Luser
103 luser_group | LuserGroup
104 luser-opts | LuserOpts
105
106=head2 inflect_plural
107
108Just like L</moniker_map> above (can be hash/code-ref, falls back to default
109if hash key does not exist or coderef returns false), but acts as a map
110for pluralizing relationship names. The default behavior is to utilize
111L<Lingua::EN::Inflect::Number/to_PL>.
112
113=head2 inflect_singular
114
115As L</inflect_plural> above, but for singularizing relationship names.
116Default behavior is to utilize L<Lingua::EN::Inflect::Number/to_S>.
117
118=head2 additional_base_classes
119
120List of additional base classes all of your table classes will use.
121
122=head2 left_base_classes
123
124List of additional base classes all of your table classes will use
125that need to be leftmost.
126
127=head2 additional_classes
128
129List of additional classes which all of your table classes will use.
130
131=head2 components
132
133List of additional components to be loaded into all of your table
134classes. A good example would be C<ResultSetManager>.
135
136=head2 resultset_components
137
8f9d7ce5 138List of additional ResultSet components to be loaded into your table
996be9ee 139classes. A good example would be C<AlwaysRS>. Component
140C<ResultSetManager> will be automatically added to the above
141C<components> list if this option is set.
142
996be9ee 143=head2 dump_directory
144
145This option is designed to be a tool to help you transition from this
146loader to a manually-defined schema when you decide it's time to do so.
147
148The value of this option is a perl libdir pathname. Within
149that directory this module will create a baseline manual
150L<DBIx::Class::Schema> module set, based on what it creates at runtime
151in memory.
152
153The created schema class will have the same classname as the one on
154which you are setting this option (and the ResultSource classes will be
7cab3ab7 155based on this name as well).
996be9ee 156
8f9d7ce5 157Normally you wouldn't hard-code this setting in your schema class, as it
996be9ee 158is meant for one-time manual usage.
159
160See L<DBIx::Class::Schema::Loader/dump_to_dir> for examples of the
161recommended way to access this functionality.
162
d65cda9e 163=head2 dump_overwrite
164
7cab3ab7 165Default false. If true, Loader will unconditionally delete any existing
166files before creating the new ones from scratch when dumping a schema to disk.
167
168The default behavior is instead to only replace the top portion of the
169file, up to and including the final stanza which contains
170C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!>
171leaving any customizations you placed after that as they were.
172
173When C<dump_overwrite> is not set, if the output file already exists,
174but the aforementioned final stanza is not found, or the checksum
175contained there does not match the generated contents, Loader will
176croak and not touch the file.
d65cda9e 177
996be9ee 178=head1 METHODS
179
180None of these methods are intended for direct invocation by regular
181users of L<DBIx::Class::Schema::Loader>. Anything you can find here
182can also be found via standard L<DBIx::Class::Schema> methods somehow.
183
184=cut
185
186# ensure that a peice of object data is a valid arrayref, creating
187# an empty one or encapsulating whatever's there.
188sub _ensure_arrayref {
189 my $self = shift;
190
191 foreach (@_) {
192 $self->{$_} ||= [];
193 $self->{$_} = [ $self->{$_} ]
194 unless ref $self->{$_} eq 'ARRAY';
195 }
196}
197
198=head2 new
199
200Constructor for L<DBIx::Class::Schema::Loader::Base>, used internally
201by L<DBIx::Class::Schema::Loader>.
202
203=cut
204
205sub new {
206 my ( $class, %args ) = @_;
207
208 my $self = { %args };
209
210 bless $self => $class;
211
212 $self->{db_schema} ||= '';
213 $self->_ensure_arrayref(qw/additional_classes
214 additional_base_classes
215 left_base_classes
216 components
217 resultset_components
218 /);
219
220 push(@{$self->{components}}, 'ResultSetManager')
221 if @{$self->{resultset_components}};
222
223 $self->{monikers} = {};
224 $self->{classes} = {};
225
996be9ee 226 $self->{schema_class} ||= ( ref $self->{schema} || $self->{schema} );
227 $self->{schema} ||= $self->{schema_class};
228
e8ad6491 229 $self->{relbuilder} = DBIx::Class::Schema::Loader::RelBuilder->new(
230 $self->schema_class, $self->inflect_plural, $self->inflect_singular
231 ) if !$self->{skip_relationships};
232
996be9ee 233 $self;
234}
235
419a2eeb 236sub _find_file_in_inc {
237 my ($self, $file) = @_;
238
239 foreach my $prefix (@INC) {
240 my $fullpath = $prefix . '/' . $file;
241 return $fullpath if -f $fullpath;
242 }
243
244 return;
245}
246
996be9ee 247sub _load_external {
f96ef30f 248 my ($self, $class) = @_;
249
250 my $class_path = $class;
251 $class_path =~ s{::}{/}g;
252 $class_path .= '.pm';
253
254 my $inc_path = $self->_find_file_in_inc($class_path);
255
256 return if !$inc_path;
257
258 my $real_dump_path = $self->dump_directory
259 ? Cwd::abs_path(
260 File::Spec->catfile($self->dump_directory, $class_path)
261 )
262 : '';
263 my $real_inc_path = Cwd::abs_path($inc_path);
264 return if $real_inc_path eq $real_dump_path;
265
266 $class->require;
267 croak "Failed to load external class definition"
268 . " for '$class': $@"
269 if $@;
270
271 # If we make it to here, we loaded an external definition
272 warn qq/# Loaded external class definition for '$class'\n/
273 if $self->debug;
274
275 # The rest is only relevant when dumping
276 return if !$self->dump_directory;
277
278 croak 'Failed to locate actual external module file for '
279 . "'$class'"
280 if !$real_inc_path;
281 open(my $fh, '<', $real_inc_path)
282 or croak "Failed to open '$real_inc_path' for reading: $!";
283 $self->_ext_stmt($class,
284 qq|# These lines were loaded from '$real_inc_path' found in \@INC.|
285 .q|# They are now part of the custom portion of this file|
286 .q|# for you to hand-edit. If you do not either delete|
287 .q|# this section or remove that file from @INC, this section|
288 .q|# will be repeated redundantly when you re-create this|
289 .q|# file again via Loader!|
290 );
291 while(<$fh>) {
292 chomp;
293 $self->_ext_stmt($class, $_);
996be9ee 294 }
f96ef30f 295 $self->_ext_stmt($class,
296 q|# End of lines loaded from '$real_inc_path' |
297 );
298 close($fh)
299 or croak "Failed to close $real_inc_path: $!";
996be9ee 300}
301
302=head2 load
303
304Does the actual schema-construction work.
305
306=cut
307
308sub load {
309 my $self = shift;
310
b97c2c1e 311 $self->_load_tables($self->_tables_list);
312}
313
314=head2 rescan
315
316Rescan the database for newly added tables. Does
317not process drops or changes.
318
319=cut
320
321sub rescan {
322 my $self = shift;
323
324 my @created;
325 my @current = $self->_tables_list;
326 foreach my $table ($self->_tables_list) {
327 if(!exists $self->{_tables}->{$table}) {
328 push(@created, $table);
329 }
330 }
331
332 $self->_load_tables(@created);
333}
334
335sub _load_tables {
336 my ($self, @tables) = @_;
337
f96ef30f 338 # First, use _tables_list with constraint and exclude
339 # to get a list of tables to operate on
340
341 my $constraint = $self->constraint;
342 my $exclude = $self->exclude;
f96ef30f 343
b97c2c1e 344 @tables = grep { /$constraint/ } @tables if $constraint;
345 @tables = grep { ! /$exclude/ } @tables if $exclude;
f96ef30f 346
b97c2c1e 347 # Save the new tables to the tables list
348 push(@{$self->{_tables}}, @tables);
f96ef30f 349
350 # Set up classes/monikers
351 {
352 no warnings 'redefine';
353 local *Class::C3::reinitialize = sub { };
354 use warnings;
355
356 $self->_make_src_class($_) for @tables;
357 }
358
359 Class::C3::reinitialize;
360
361 $self->_setup_src_meta($_) for @tables;
362
e8ad6491 363 if(!$self->skip_relationships) {
364 $self->_load_relationships($_) for @tables;
365 }
366
f96ef30f 367 $self->_load_external($_)
75451704 368 for map { $self->classes->{$_} } @tables;
f96ef30f 369
996be9ee 370 $self->_dump_to_dir if $self->dump_directory;
371
5223f24a 372 # Drop temporary cache
373 delete $self->{_cache};
374
996be9ee 375 1;
376}
377
378sub _get_dump_filename {
379 my ($self, $class) = (@_);
380
381 $class =~ s{::}{/}g;
382 return $self->dump_directory . q{/} . $class . q{.pm};
383}
384
385sub _ensure_dump_subdirs {
386 my ($self, $class) = (@_);
387
388 my @name_parts = split(/::/, $class);
dd03ee1a 389 pop @name_parts; # we don't care about the very last element,
390 # which is a filename
391
996be9ee 392 my $dir = $self->dump_directory;
7cab3ab7 393 while (1) {
394 if(!-d $dir) {
25328cc4 395 mkdir($dir) or croak "mkdir('$dir') failed: $!";
996be9ee 396 }
7cab3ab7 397 last if !@name_parts;
398 $dir = File::Spec->catdir($dir, shift @name_parts);
996be9ee 399 }
400}
401
402sub _dump_to_dir {
403 my ($self) = @_;
404
405 my $target_dir = $self->dump_directory;
d65cda9e 406
fc2b71fd 407 my $schema_class = $self->schema_class;
996be9ee 408
25328cc4 409 croak "Must specify target directory for dumping!" if ! $target_dir;
996be9ee 410
fc2b71fd 411 warn "Dumping manual schema for $schema_class to directory $target_dir ...\n";
996be9ee 412
7cab3ab7 413 my $schema_text =
414 qq|package $schema_class;\n\n|
415 . qq|use strict;\nuse warnings;\n\n|
416 . qq|use base 'DBIx::Class::Schema';\n\n|
417 . qq|__PACKAGE__->load_classes;\n|;
996be9ee 418
7cab3ab7 419 $self->_write_classfile($schema_class, $schema_text);
996be9ee 420
7cab3ab7 421 foreach my $src_class (sort keys %{$self->{_dump_storage}}) {
422 my $src_text =
423 qq|package $src_class;\n\n|
424 . qq|use strict;\nuse warnings;\n\n|
425 . qq|use base 'DBIx::Class';\n\n|;
996be9ee 426
7cab3ab7 427 $self->_write_classfile($src_class, $src_text);
02356864 428 }
996be9ee 429
7cab3ab7 430 warn "Schema dump completed.\n";
431}
432
433sub _write_classfile {
434 my ($self, $class, $text) = @_;
435
436 my $filename = $self->_get_dump_filename($class);
437 $self->_ensure_dump_subdirs($class);
438
439 if (-f $filename && $self->dump_overwrite) {
440 warn "Deleting existing file '$filename' due to "
441 . "'dump_overwrite' setting\n";
442 unlink($filename);
443 }
444
419a2eeb 445 my $custom_content = $self->_get_custom_content($class, $filename);
7cab3ab7 446
447 $custom_content ||= qq|\n# You can replace this text with custom|
448 . qq| content, and it will be preserved on regeneration|
449 . qq|\n1;\n|;
450
451 $text .= qq|$_\n|
452 for @{$self->{_dump_storage}->{$class} || []};
453
454 $text .= qq|\n\n# Created by DBIx::Class::Schema::Loader|
455 . qq| v| . $DBIx::Class::Schema::Loader::VERSION
456 . q| @ | . POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime)
457 . qq|\n# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:|;
458
459 open(my $fh, '>', $filename)
460 or croak "Cannot open '$filename' for writing: $!";
461
462 # Write the top half and its MD5 sum
463 print $fh $text . Digest::MD5::md5_base64($text) . "\n\n";
464
465 # Write out anything loaded via external partial class file in @INC
466 print $fh qq|$_\n|
467 for @{$self->{_ext_storage}->{$class} || []};
468
469 print $fh $custom_content;
470
471 close($fh)
472 or croak "Cannot close '$filename': $!";
473}
474
475sub _get_custom_content {
476 my ($self, $class, $filename) = @_;
477
478 return if ! -f $filename;
479 open(my $fh, '<', $filename)
480 or croak "Cannot open '$filename' for reading: $!";
481
482 my $mark_re =
419a2eeb 483 qr{^(# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:)([A-Za-z0-9/+]{22})\n};
7cab3ab7 484
485 my $found = 0;
486 my $buffer = '';
487 while(<$fh>) {
488 if(!$found && /$mark_re/) {
489 $found = 1;
490 $buffer .= $1;
7cab3ab7 491 croak "Checksum mismatch in '$filename'"
419a2eeb 492 if Digest::MD5::md5_base64($buffer) ne $2;
7cab3ab7 493
494 $buffer = '';
495 }
496 else {
497 $buffer .= $_;
498 }
996be9ee 499 }
500
5ef3c771 501 croak "Cannot not overwrite '$filename' without 'dump_overwrite',"
419a2eeb 502 . " it does not appear to have been generated by Loader"
5ef3c771 503 if !$found;
504
7cab3ab7 505 return $buffer;
996be9ee 506}
507
508sub _use {
509 my $self = shift;
510 my $target = shift;
cb54990b 511 my $evalstr;
996be9ee 512
513 foreach (@_) {
cb54990b 514 warn "$target: use $_;" if $self->debug;
996be9ee 515 $self->_raw_stmt($target, "use $_;");
cb54990b 516 $_->require or croak ($_ . "->require: $@");
517 $evalstr .= "package $target; use $_;";
996be9ee 518 }
cb54990b 519 eval $evalstr if $evalstr;
520 croak $@ if $@;
996be9ee 521}
522
523sub _inject {
524 my $self = shift;
525 my $target = shift;
526 my $schema_class = $self->schema_class;
527
528 my $blist = join(q{ }, @_);
cb54990b 529 warn "$target: use base qw/ $blist /;" if $self->debug && @_;
996be9ee 530 $self->_raw_stmt($target, "use base qw/ $blist /;") if @_;
996be9ee 531 foreach (@_) {
532 $_->require or croak ($_ . "->require: $@");
533 $schema_class->inject_base($target, $_);
534 }
535}
536
f96ef30f 537# Create class with applicable bases, setup monikers, etc
538sub _make_src_class {
539 my ($self, $table) = @_;
996be9ee 540
a13b2803 541 my $schema = $self->schema;
542 my $schema_class = $self->schema_class;
996be9ee 543
f96ef30f 544 my $table_moniker = $self->_table2moniker($table);
545 my $table_class = $schema_class . q{::} . $table_moniker;
996be9ee 546
f96ef30f 547 my $table_normalized = lc $table;
548 $self->classes->{$table} = $table_class;
549 $self->classes->{$table_normalized} = $table_class;
550 $self->monikers->{$table} = $table_moniker;
551 $self->monikers->{$table_normalized} = $table_moniker;
996be9ee 552
f96ef30f 553 { no strict 'refs'; @{"${table_class}::ISA"} = qw/DBIx::Class/ }
996be9ee 554
f96ef30f 555 $self->_use ($table_class, @{$self->additional_classes});
556 $self->_inject($table_class, @{$self->additional_base_classes});
996be9ee 557
f96ef30f 558 $self->_dbic_stmt($table_class, 'load_components', @{$self->components}, qw/PK::Auto Core/);
996be9ee 559
f96ef30f 560 $self->_dbic_stmt($table_class, 'load_resultset_components', @{$self->resultset_components})
561 if @{$self->resultset_components};
562 $self->_inject($table_class, @{$self->left_base_classes});
563}
996be9ee 564
f96ef30f 565# Set up metadata (cols, pks, etc) and register the class with the schema
566sub _setup_src_meta {
567 my ($self, $table) = @_;
996be9ee 568
f96ef30f 569 my $schema = $self->schema;
570 my $schema_class = $self->schema_class;
a13b2803 571
f96ef30f 572 my $table_class = $self->classes->{$table};
573 my $table_moniker = $self->monikers->{$table};
996be9ee 574
f96ef30f 575 $self->_dbic_stmt($table_class,'table',$table);
996be9ee 576
f96ef30f 577 my $cols = $self->_table_columns($table);
578 my $col_info;
579 eval { $col_info = $self->_columns_info_for($table) };
580 if($@) {
581 $self->_dbic_stmt($table_class,'add_columns',@$cols);
582 }
583 else {
584 my %col_info_lc = map { lc($_), $col_info->{$_} } keys %$col_info;
585 $self->_dbic_stmt(
586 $table_class,
587 'add_columns',
588 map { $_, ($col_info_lc{$_}||{}) } @$cols
589 );
996be9ee 590 }
591
f96ef30f 592 my $pks = $self->_table_pk_info($table) || [];
593 @$pks ? $self->_dbic_stmt($table_class,'set_primary_key',@$pks)
594 : carp("$table has no primary key");
996be9ee 595
f96ef30f 596 my $uniqs = $self->_table_uniq_info($table) || [];
597 $self->_dbic_stmt($table_class,'add_unique_constraint',@$_) for (@$uniqs);
996be9ee 598
f96ef30f 599 $schema_class->register_class($table_moniker, $table_class);
600 $schema->register_class($table_moniker, $table_class) if $schema ne $schema_class;
996be9ee 601}
602
603=head2 tables
604
605Returns a sorted list of loaded tables, using the original database table
606names.
607
608=cut
609
610sub tables {
611 my $self = shift;
612
b97c2c1e 613 return keys %{$self->_tables};
996be9ee 614}
615
616# Make a moniker from a table
617sub _table2moniker {
618 my ( $self, $table ) = @_;
619
620 my $moniker;
621
622 if( ref $self->moniker_map eq 'HASH' ) {
623 $moniker = $self->moniker_map->{$table};
624 }
625 elsif( ref $self->moniker_map eq 'CODE' ) {
626 $moniker = $self->moniker_map->($table);
627 }
628
629 $moniker ||= join '', map ucfirst, split /[\W_]+/, lc $table;
630
631 return $moniker;
632}
633
634sub _load_relationships {
e8ad6491 635 my ($self, $table) = @_;
996be9ee 636
e8ad6491 637 my $tbl_fk_info = $self->_table_fk_info($table);
638 foreach my $fkdef (@$tbl_fk_info) {
639 $fkdef->{remote_source} =
640 $self->monikers->{delete $fkdef->{remote_table}};
996be9ee 641 }
642
e8ad6491 643 my $local_moniker = $self->monikers->{$table};
644 my $rel_stmts = $self->{relbuilder}->generate_code($local_moniker, $tbl_fk_info);
996be9ee 645
996be9ee 646 foreach my $src_class (sort keys %$rel_stmts) {
647 my $src_stmts = $rel_stmts->{$src_class};
648 foreach my $stmt (@$src_stmts) {
649 $self->_dbic_stmt($src_class,$stmt->{method},@{$stmt->{args}});
650 }
651 }
652}
653
654# Overload these in driver class:
655
656# Returns an arrayref of column names
657sub _table_columns { croak "ABSTRACT METHOD" }
658
659# Returns arrayref of pk col names
660sub _table_pk_info { croak "ABSTRACT METHOD" }
661
662# Returns an arrayref of uniqs [ [ foo => [ col1, col2 ] ], [ bar => [ ... ] ] ]
663sub _table_uniq_info { croak "ABSTRACT METHOD" }
664
665# Returns an arrayref of foreign key constraints, each
666# being a hashref with 3 keys:
667# local_columns (arrayref), remote_columns (arrayref), remote_table
668sub _table_fk_info { croak "ABSTRACT METHOD" }
669
670# Returns an array of lower case table names
671sub _tables_list { croak "ABSTRACT METHOD" }
672
673# Execute a constructive DBIC class method, with debug/dump_to_dir hooks.
674sub _dbic_stmt {
675 my $self = shift;
676 my $class = shift;
677 my $method = shift;
678
679 if(!$self->debug && !$self->dump_directory) {
680 $class->$method(@_);
681 return;
682 }
683
684 my $args = dump(@_);
685 $args = '(' . $args . ')' if @_ < 2;
686 my $stmt = $method . $args . q{;};
687
688 warn qq|$class\->$stmt\n| if $self->debug;
689 $class->$method(@_);
690 $self->_raw_stmt($class, '__PACKAGE__->' . $stmt);
691}
692
693# Store a raw source line for a class (for dumping purposes)
694sub _raw_stmt {
695 my ($self, $class, $stmt) = @_;
696 push(@{$self->{_dump_storage}->{$class}}, $stmt) if $self->dump_directory;
697}
698
7cab3ab7 699# Like above, but separately for the externally loaded stuff
700sub _ext_stmt {
701 my ($self, $class, $stmt) = @_;
702 push(@{$self->{_ext_storage}->{$class}}, $stmt) if $self->dump_directory;
703}
704
996be9ee 705=head2 monikers
706
8f9d7ce5 707Returns a hashref of loaded table to moniker mappings. There will
996be9ee 708be two entries for each table, the original name and the "normalized"
709name, in the case that the two are different (such as databases
710that like uppercase table names, or preserve your original mixed-case
711definitions, or what-have-you).
712
713=head2 classes
714
8f9d7ce5 715Returns a hashref of table to class mappings. In some cases it will
996be9ee 716contain multiple entries per table for the original and normalized table
717names, as above in L</monikers>.
718
719=head1 SEE ALSO
720
721L<DBIx::Class::Schema::Loader>
722
723=cut
724
7251;