Storage holds a weakref to $schema now
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
CommitLineData
a02675cd 1package DBIx::Class::Schema;
2
3use strict;
4use warnings;
aa562407 5
701da8c4 6use Carp::Clan qw/^DBIx::Class/;
a917fb06 7use Scalar::Util qw/weaken/;
a02675cd 8
41a6f8c0 9use base qw/DBIx::Class/;
a02675cd 10
0dc79249 11__PACKAGE__->mk_classdata('class_mappings' => {});
12__PACKAGE__->mk_classdata('source_registrations' => {});
1e10a11d 13__PACKAGE__->mk_classdata('storage_type' => '::DBI');
d7156e50 14__PACKAGE__->mk_classdata('storage');
82cc0386 15__PACKAGE__->mk_classdata('exception_action');
a02675cd 16
c2da098a 17=head1 NAME
18
19DBIx::Class::Schema - composable schemas
20
21=head1 SYNOPSIS
22
24d67825 23 package Library::Schema;
c2da098a 24 use base qw/DBIx::Class::Schema/;
bab77431 25
24d67825 26 # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
27 __PACKAGE__->load_classes(qw/CD Book DVD/);
c2da098a 28
24d67825 29 package Library::Schema::CD;
03312470 30 use base qw/DBIx::Class/;
77254782 31 __PACKAGE__->load_components(qw/PK::Auto Core/); # for example
24d67825 32 __PACKAGE__->table('cd');
c2da098a 33
5d9076f2 34 # Elsewhere in your code:
24d67825 35 my $schema1 = Library::Schema->connect(
a3d93194 36 $dsn,
37 $user,
38 $password,
24d67825 39 { AutoCommit => 0 },
a3d93194 40 );
bab77431 41
24d67825 42 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 43
24d67825 44 # fetch objects using Library::Schema::DVD
45 my $resultset = $schema1->resultset('DVD')->search( ... );
46 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 47
48=head1 DESCRIPTION
49
a3d93194 50Creates database classes based on a schema. This is the recommended way to
51use L<DBIx::Class> and allows you to use more than one concurrent connection
52with your classes.
429bd4f1 53
03312470 54NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 55carefully, as DBIx::Class does things a little differently. Note in
03312470 56particular which module inherits off which.
57
c2da098a 58=head1 METHODS
59
87c4e602 60=head2 register_class
61
27f01d1f 62=over 4
63
ebc77b53 64=item Arguments: $moniker, $component_class
27f01d1f 65
66=back
076652e8 67
71f9df37 68Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
2053ab2a 69calling:
66d9ef6b 70
181a28f4 71 $schema->register_source($moniker, $component_class->result_source_instance);
076652e8 72
c2da098a 73=cut
74
a02675cd 75sub register_class {
0dc79249 76 my ($self, $moniker, $to_register) = @_;
77 $self->register_source($moniker => $to_register->result_source_instance);
74b92d9a 78}
79
87c4e602 80=head2 register_source
81
27f01d1f 82=over 4
83
ebc77b53 84=item Arguments: $moniker, $result_source
27f01d1f 85
86=back
076652e8 87
82b01c38 88Registers the L<DBIx::Class::ResultSource> in the schema with the given
89moniker.
076652e8 90
91=cut
92
0dc79249 93sub register_source {
94 my ($self, $moniker, $source) = @_;
95 my %reg = %{$self->source_registrations};
96 $reg{$moniker} = $source;
97 $self->source_registrations(\%reg);
98 $source->schema($self);
a917fb06 99 weaken($source->{schema}) if ref($self);
0dc79249 100 if ($source->result_class) {
101 my %map = %{$self->class_mappings};
102 $map{$source->result_class} = $moniker;
103 $self->class_mappings(\%map);
104 }
75d07914 105}
a02675cd 106
bfb2bd4f 107=head2 class
108
27f01d1f 109=over 4
82b01c38 110
ebc77b53 111=item Arguments: $moniker
27f01d1f 112
d601dc88 113=item Return Value: $classname
27f01d1f 114
115=back
82b01c38 116
2053ab2a 117Retrieves the result class name for the given moniker. For example:
82b01c38 118
119 my $class = $schema->class('CD');
bfb2bd4f 120
121=cut
122
123sub class {
0dc79249 124 my ($self, $moniker) = @_;
125 return $self->source($moniker)->result_class;
bfb2bd4f 126}
127
ea20d0fd 128=head2 source
129
27f01d1f 130=over 4
131
ebc77b53 132=item Arguments: $moniker
27f01d1f 133
d601dc88 134=item Return Value: $result_source
82b01c38 135
27f01d1f 136=back
82b01c38 137
24d67825 138 my $source = $schema->source('Book');
ea20d0fd 139
82b01c38 140Returns the L<DBIx::Class::ResultSource> object for the registered moniker.
ea20d0fd 141
142=cut
143
144sub source {
0dc79249 145 my ($self, $moniker) = @_;
146 my $sreg = $self->source_registrations;
147 return $sreg->{$moniker} if exists $sreg->{$moniker};
148
149 # if we got here, they probably passed a full class name
150 my $mapped = $self->class_mappings->{$moniker};
701da8c4 151 $self->throw_exception("Can't find source for ${moniker}")
0dc79249 152 unless $mapped && exists $sreg->{$mapped};
153 return $sreg->{$mapped};
ea20d0fd 154}
155
0dc79249 156=head2 sources
157
27f01d1f 158=over 4
159
d601dc88 160=item Return Value: @source_monikers
27f01d1f 161
162=back
82b01c38 163
164Returns the source monikers of all source registrations on this schema.
2053ab2a 165For example:
82b01c38 166
167 my @source_monikers = $schema->sources;
0dc79249 168
169=cut
170
171sub sources { return keys %{shift->source_registrations}; }
172
ea20d0fd 173=head2 resultset
174
27f01d1f 175=over 4
176
ebc77b53 177=item Arguments: $moniker
27f01d1f 178
d601dc88 179=item Return Value: $result_set
82b01c38 180
27f01d1f 181=back
82b01c38 182
24d67825 183 my $rs = $schema->resultset('DVD');
ea20d0fd 184
82b01c38 185Returns the L<DBIx::Class::ResultSet> object for the registered moniker.
ea20d0fd 186
187=cut
188
189sub resultset {
0dc79249 190 my ($self, $moniker) = @_;
191 return $self->source($moniker)->resultset;
ea20d0fd 192}
193
87c4e602 194=head2 load_classes
195
27f01d1f 196=over 4
197
198=item Arguments: @classes?, { $namespace => [ @classes ] }+
199
200=back
076652e8 201
82b01c38 202With no arguments, this method uses L<Module::Find> to find all classes under
203the schema's namespace. Otherwise, this method loads the classes you specify
204(using L<use>), and registers them (using L</"register_class">).
076652e8 205
2053ab2a 206It is possible to comment out classes with a leading C<#>, but note that perl
207will think it's a mistake (trying to use a comment in a qw list), so you'll
208need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 209
2053ab2a 210Example:
82b01c38 211
212 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 213 # etc. (anything under the My::Schema namespace)
82b01c38 214
215 # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
216 # not Other::Namespace::LinerNotes nor My::Schema::Track
217 My::Schema->load_classes(qw/ CD Artist #Track /, {
218 Other::Namespace => [qw/ Producer #LinerNotes /],
219 });
220
076652e8 221=cut
222
a02675cd 223sub load_classes {
5ce32fc1 224 my ($class, @params) = @_;
bab77431 225
5ce32fc1 226 my %comps_for;
bab77431 227
5ce32fc1 228 if (@params) {
229 foreach my $param (@params) {
230 if (ref $param eq 'ARRAY') {
231 # filter out commented entries
232 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 233
5ce32fc1 234 push (@{$comps_for{$class}}, @modules);
235 }
236 elsif (ref $param eq 'HASH') {
237 # more than one namespace possible
238 for my $comp ( keys %$param ) {
239 # filter out commented entries
240 my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
241
242 push (@{$comps_for{$comp}}, @modules);
243 }
244 }
245 else {
246 # filter out commented entries
247 push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
248 }
249 }
250 } else {
41a6f8c0 251 eval "require Module::Find;";
bc0c9800 252 $class->throw_exception(
253 "No arguments to load_classes and couldn't load Module::Find ($@)"
254 ) if $@;
255 my @comp = map { substr $_, length "${class}::" }
256 Module::Find::findallmod($class);
5ce32fc1 257 $comps_for{$class} = \@comp;
41a6f8c0 258 }
5ce32fc1 259
e6efde04 260 my @to_register;
261 {
262 no warnings qw/redefine/;
263 local *Class::C3::reinitialize = sub { };
264 foreach my $prefix (keys %comps_for) {
265 foreach my $comp (@{$comps_for{$prefix}||[]}) {
266 my $comp_class = "${prefix}::${comp}";
c037c03a 267 $class->ensure_class_loaded($comp_class);
bab77431 268 $comp_class->source_name($comp) unless $comp_class->source_name;
269
270 push(@to_register, [ $comp_class->source_name, $comp_class ]);
bfb2bd4f 271 }
5ce32fc1 272 }
a02675cd 273 }
e6efde04 274 Class::C3->reinitialize;
275
276 foreach my $to (@to_register) {
277 $class->register_class(@$to);
278 # if $class->can('result_source_instance');
279 }
a02675cd 280}
281
87c4e602 282=head2 compose_connection
283
27f01d1f 284=over 4
285
ebc77b53 286=item Arguments: $target_namespace, @db_info
429bd4f1 287
d601dc88 288=item Return Value: $new_schema
27f01d1f 289
290=back
076652e8 291
2053ab2a 292Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
293calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
294then injects the L<DBix::Class::ResultSetProxy> component and a
295resultset_instance classdata entry on all the new classes, in order to support
82b01c38 296$target_namespaces::$class->search(...) method calls.
297
298This is primarily useful when you have a specific need for class method access
299to a connection. In normal usage it is preferred to call
300L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
301on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
302more information.
54540863 303
076652e8 304=cut
305
a02675cd 306sub compose_connection {
ea20d0fd 307 my ($self, $target, @info) = @_;
80c90f5d 308 my $base = 'DBIx::Class::ResultSetProxy';
8ef144ff 309 eval "require ${base};";
bc0c9800 310 $self->throw_exception
311 ("No arguments to load_classes and couldn't load ${base} ($@)")
312 if $@;
be381829 313
314 if ($self eq $target) {
315 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
316 foreach my $moniker ($self->sources) {
317 my $source = $self->source($moniker);
318 my $class = $source->result_class;
319 $self->inject_base($class, $base);
320 $class->mk_classdata(resultset_instance => $source->resultset);
321 $class->mk_classdata(class_resolver => $self);
322 }
50041f3c 323 $self->connection(@info);
be381829 324 return $self;
325 }
326
66d9ef6b 327 my $schema = $self->compose_namespace($target, $base);
ecceadff 328 {
329 no strict 'refs';
330 *{"${target}::schema"} = sub { $schema };
331 }
332
66d9ef6b 333 $schema->connection(@info);
0dc79249 334 foreach my $moniker ($schema->sources) {
335 my $source = $schema->source($moniker);
336 my $class = $source->result_class;
337 #warn "$moniker $class $source ".$source->storage;
8c49f629 338 $class->mk_classdata(result_source_instance => $source);
ea20d0fd 339 $class->mk_classdata(resultset_instance => $source->resultset);
66d9ef6b 340 $class->mk_classdata(class_resolver => $schema);
bfb2bd4f 341 }
342 return $schema;
e678398e 343}
344
77254782 345=head2 compose_namespace
346
27f01d1f 347=over 4
348
349=item Arguments: $target_namespace, $additional_base_class?
82b01c38 350
d601dc88 351=item Return Value: $new_schema
27f01d1f 352
353=back
13765dad 354
82b01c38 355For each L<DBIx::Class::ResultSource> in the schema, this method creates a
356class in the target namespace (e.g. $target_namespace::CD,
357$target_namespace::Artist) that inherits from the corresponding classes
358attached to the current schema.
77254782 359
82b01c38 360It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
361new $schema object. If C<$additional_base_class> is given, the new composed
362classes will inherit from first the corresponding classe from the current
363schema then the base class.
364
2053ab2a 365For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
82b01c38 366
367 $schema->compose_namespace('My::DB', 'Base::Class');
368 print join (', ', @My::DB::CD::ISA) . "\n";
369 print join (', ', @My::DB::Artist::ISA) ."\n";
370
2053ab2a 371will produce the output
82b01c38 372
373 My::Schema::CD, Base::Class
374 My::Schema::Artist, Base::Class
77254782 375
376=cut
377
e678398e 378sub compose_namespace {
66d9ef6b 379 my ($self, $target, $base) = @_;
380 my %reg = %{ $self->source_registrations };
11b78bd6 381 my %target;
382 my %map;
66d9ef6b 383 my $schema = $self->clone;
e9100ff7 384 {
385 no warnings qw/redefine/;
386 local *Class::C3::reinitialize = sub { };
387 foreach my $moniker ($schema->sources) {
388 my $source = $schema->source($moniker);
389 my $target_class = "${target}::${moniker}";
390 $self->inject_base(
391 $target_class => $source->result_class, ($base ? $base : ())
392 );
393 $source->result_class($target_class);
9d3d5af3 394 $target_class->result_source_instance($source)
395 if $target_class->can('result_source_instance');
e9100ff7 396 }
b7951443 397 }
e9100ff7 398 Class::C3->reinitialize();
11b78bd6 399 {
400 no strict 'refs';
1edaf6fe 401 foreach my $meth (qw/class source resultset/) {
402 *{"${target}::${meth}"} =
403 sub { shift->schema->$meth(@_) };
404 }
11b78bd6 405 }
bfb2bd4f 406 return $schema;
b7951443 407}
408
87c4e602 409=head2 setup_connection_class
410
27f01d1f 411=over 4
412
ebc77b53 413=item Arguments: $target, @info
27f01d1f 414
415=back
076652e8 416
82b01c38 417Sets up a database connection class to inject between the schema and the
418subclasses that the schema creates.
429bd4f1 419
076652e8 420=cut
421
b7951443 422sub setup_connection_class {
423 my ($class, $target, @info) = @_;
63e9583a 424 $class->inject_base($target => 'DBIx::Class::DB');
425 #$target->load_components('DB');
b7951443 426 $target->connection(@info);
427}
428
87c4e602 429=head2 connection
430
27f01d1f 431=over 4
432
ebc77b53 433=item Arguments: @args
66d9ef6b 434
d601dc88 435=item Return Value: $new_schema
27f01d1f 436
437=back
82b01c38 438
439Instantiates a new Storage object of type
440L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
441$storage->connect_info. Sets the connection in-place on the schema. See
442L<DBIx::Class::Storage::DBI/"connect_info"> for more information.
66d9ef6b 443
444=cut
445
446sub connection {
447 my ($self, @info) = @_;
e59d3e5b 448 return $self if !@info && $self->storage;
1e10a11d 449 my $storage_class = $self->storage_type;
450 $storage_class = 'DBIx::Class::Storage'.$storage_class
451 if $storage_class =~ m/^::/;
8ef144ff 452 eval "require ${storage_class};";
bc0c9800 453 $self->throw_exception(
454 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
455 ) if $@;
82cc0386 456 my $storage = $storage_class->new($self);
66d9ef6b 457 $storage->connect_info(\@info);
458 $self->storage($storage);
459 return $self;
460}
461
87c4e602 462=head2 connect
463
27f01d1f 464=over 4
465
ebc77b53 466=item Arguments: @info
66d9ef6b 467
d601dc88 468=item Return Value: $new_schema
27f01d1f 469
470=back
82b01c38 471
472This is a convenience method. It is equivalent to calling
473$schema->clone->connection(@info). See L</connection> and L</clone> for more
474information.
66d9ef6b 475
476=cut
477
08b515f1 478sub connect { shift->clone->connection(@_) }
479
480=head2 txn_begin
481
82b01c38 482Begins a transaction (does nothing if AutoCommit is off). Equivalent to
483calling $schema->storage->txn_begin. See
484L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
08b515f1 485
486=cut
487
488sub txn_begin { shift->storage->txn_begin }
489
490=head2 txn_commit
491
82b01c38 492Commits the current transaction. Equivalent to calling
493$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
494for more information.
08b515f1 495
496=cut
497
498sub txn_commit { shift->storage->txn_commit }
499
500=head2 txn_rollback
501
82b01c38 502Rolls back the current transaction. Equivalent to calling
503$schema->storage->txn_rollback. See
504L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
08b515f1 505
506=cut
507
508sub txn_rollback { shift->storage->txn_rollback }
66d9ef6b 509
a62cf8d4 510=head2 txn_do
511
27f01d1f 512=over 4
513
ebc77b53 514=item Arguments: C<$coderef>, @coderef_args?
82b01c38 515
d601dc88 516=item Return Value: The return value of $coderef
27f01d1f 517
518=back
a62cf8d4 519
82b01c38 520Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
521returning its result (if any). If an exception is caught, a rollback is issued
522and the exception is rethrown. If the rollback fails, (i.e. throws an
523exception) an exception is thrown that includes a "Rollback failed" message.
a62cf8d4 524
525For example,
526
24d67825 527 my $author_rs = $schema->resultset('Author')->find(1);
70634260 528 my @titles = qw/Night Day It/;
a62cf8d4 529
530 my $coderef = sub {
a62cf8d4 531 # If any one of these fails, the entire transaction fails
70634260 532 $author_rs->create_related('books', {
24d67825 533 title => $_
534 }) foreach (@titles);
a62cf8d4 535
24d67825 536 return $author->books;
a62cf8d4 537 };
538
539 my $rs;
540 eval {
70634260 541 $rs = $schema->txn_do($coderef);
a62cf8d4 542 };
543
70634260 544 if ($@) { # Transaction failed
545 die "something terrible has happened!" #
546 if ($@ =~ /Rollback failed/); # Rollback failed
547
548 deal_with_failed_transaction();
a62cf8d4 549 }
550
82b01c38 551In a nested transaction (calling txn_do() from within a txn_do() coderef) only
552the outermost transaction will issue a L<DBIx::Class::Schema/"txn_commit"> on
553the Schema's storage, and txn_do() can be called in void, scalar and list
554context and it will behave as expected.
a62cf8d4 555
556=cut
557
558sub txn_do {
559 my ($self, $coderef, @args) = @_;
560
19630353 561 $self->storage or $self->throw_exception
562 ('txn_do called on $schema without storage');
171dadd7 563 ref $coderef eq 'CODE' or $self->throw_exception
564 ('$coderef must be a CODE reference');
a62cf8d4 565
566 my (@return_values, $return_value);
567
568 $self->txn_begin; # If this throws an exception, no rollback is needed
569
e7f2b7d5 570 my $wantarray = wantarray; # Need to save this since the context
75d07914 571 # inside the eval{} block is independent
572 # of the context that called txn_do()
a62cf8d4 573 eval {
82b01c38 574
24d67825 575 # Need to differentiate between scalar/list context to allow for
576 # returning a list in scalar context to get the size of the list
a62cf8d4 577 if ($wantarray) {
eeb34228 578 # list context
a62cf8d4 579 @return_values = $coderef->(@args);
eeb34228 580 } elsif (defined $wantarray) {
581 # scalar context
a62cf8d4 582 $return_value = $coderef->(@args);
eeb34228 583 } else {
584 # void context
585 $coderef->(@args);
a62cf8d4 586 }
587 $self->txn_commit;
588 };
589
590 if ($@) {
591 my $error = $@;
592
593 eval {
594 $self->txn_rollback;
595 };
596
597 if ($@) {
598 my $rollback_error = $@;
599 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
600 $self->throw_exception($error) # propagate nested rollback
75d07914 601 if $rollback_error =~ /$exception_class/;
a62cf8d4 602
bc0c9800 603 $self->throw_exception(
604 "Transaction aborted: $error. Rollback failed: ${rollback_error}"
605 );
a62cf8d4 606 } else {
607 $self->throw_exception($error); # txn failed but rollback succeeded
608 }
609 }
610
611 return $wantarray ? @return_values : $return_value;
612}
613
66d9ef6b 614=head2 clone
615
27f01d1f 616=over 4
617
d601dc88 618=item Return Value: $new_schema
27f01d1f 619
620=back
82b01c38 621
66d9ef6b 622Clones the schema and its associated result_source objects and returns the
623copy.
624
625=cut
626
627sub clone {
628 my ($self) = @_;
629 my $clone = bless({ (ref $self ? %$self : ()) }, ref $self || $self);
630 foreach my $moniker ($self->sources) {
631 my $source = $self->source($moniker);
632 my $new = $source->new($source);
633 $clone->register_source($moniker => $new);
634 }
82cc0386 635 $clone->storage->set_schema($clone) if $clone->storage;
66d9ef6b 636 return $clone;
637}
638
87c4e602 639=head2 populate
640
27f01d1f 641=over 4
642
ebc77b53 643=item Arguments: $moniker, \@data;
27f01d1f 644
645=back
a37a4697 646
647Populates the source registered with the given moniker with the supplied data.
82b01c38 648@data should be a list of listrefs -- the first containing column names, the
649second matching values.
650
651i.e.,
a37a4697 652
24d67825 653 $schema->populate('Artist', [
654 [ qw/artistid name/ ],
655 [ 1, 'Popular Band' ],
656 [ 2, 'Indie Band' ],
a62cf8d4 657 ...
658 ]);
a37a4697 659
660=cut
661
662sub populate {
663 my ($self, $name, $data) = @_;
664 my $rs = $self->resultset($name);
665 my @names = @{shift(@$data)};
84e3c114 666 my @created;
a37a4697 667 foreach my $item (@$data) {
668 my %create;
669 @create{@names} = @$item;
84e3c114 670 push(@created, $rs->create(\%create));
a37a4697 671 }
84e3c114 672 return @created;
a37a4697 673}
674
82cc0386 675=head2 exception_action
676
677=over 4
678
679=item Arguments: $code_reference
680
681=back
682
683If this accessor is set to a subroutine reference, it will be executed
684to handle exceptions where possible. Can be set at either the class or
685object level.
686
687Example:
688
689 package My::Schema;
690 use base qw/DBIx::Class::Schema/;
691 use My::ExceptionClass;
692 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
693 __PACKAGE__->load_classes;
694
695 # or
696 my $schema_obj = My::Schema->connect( .... );
697 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
698
5160b401 699=head2 throw_exception
701da8c4 700
75d07914 701=over 4
82b01c38 702
ebc77b53 703=item Arguments: $message
82b01c38 704
705=back
706
707Throws an exception. Defaults to using L<Carp::Clan> to report errors from
82cc0386 708user's perspective. If C<exception_action> is set for this schema class or
709object, the error will be thrown via that subref instead.
701da8c4 710
711=cut
712
713sub throw_exception {
82cc0386 714 my $self = shift;
715 $self->exception_action->(@_) if $self->exception_action;
701da8c4 716 croak @_;
717}
718
ec6704d4 719=head2 deploy (EXPERIMENTAL)
1c339d71 720
82b01c38 721=over 4
722
ebc77b53 723=item Arguments: $sqlt_args
82b01c38 724
725=back
726
727Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 728
729Note that this feature is currently EXPERIMENTAL and may not work correctly
730across all databases, or fully handle complex relationships.
1c339d71 731
51bace1c 732See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
733common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
734produced include a DROP TABLE statement for each table created.
735
1c339d71 736=cut
737
738sub deploy {
cb561d1a 739 my ($self, $sqltargs) = @_;
1c339d71 740 $self->throw_exception("Can't deploy without storage") unless $self->storage;
cb561d1a 741 $self->storage->deploy($self, undef, $sqltargs);
1c339d71 742}
743
c0f61310 744=head2 create_ddl_dir (EXPERIMENTAL)
745
746=over 4
747
748=item Arguments: \@databases, $version, $directory, $sqlt_args
749
750=back
751
752Creates an SQL file based on the Schema, for each of the specified
753database types, in the given directory.
754
755Note that this feature is currently EXPERIMENTAL and may not work correctly
756across all databases, or fully handle complex relationships.
757
758=cut
759
e673f011 760sub create_ddl_dir
761{
762 my $self = shift;
763
764 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
765 $self->storage->create_ddl_dir($self, @_);
766}
767
9b83fccd 768=head2 ddl_filename (EXPERIMENTAL)
769
770 my $filename = $table->ddl_filename($type, $dir, $version)
771
772Creates a filename for a SQL file based on the table class name. Not
773intended for direct end user use.
774
775=cut
776
e673f011 777sub ddl_filename
778{
779 my ($self, $type, $dir, $version) = @_;
780
781 my $filename = ref($self);
9e7b9292 782 $filename =~ s/::/-/;
e673f011 783 $filename = "$dir$filename-$version-$type.sql";
784
785 return $filename;
786}
787
a02675cd 7881;
c2da098a 789
c2da098a 790=head1 AUTHORS
791
daec44b8 792Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 793
794=head1 LICENSE
795
796You may distribute this code under the same terms as Perl itself.
797
798=cut
799