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