misc POD updates related to Storage/Storage::DBI
[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
85f78622 441$storage->connect_info. Sets the connection in-place on the schema.
442
443See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
444or L<DBIx::Class::Storage> in general.
66d9ef6b 445
446=cut
447
448sub connection {
449 my ($self, @info) = @_;
e59d3e5b 450 return $self if !@info && $self->storage;
1e10a11d 451 my $storage_class = $self->storage_type;
452 $storage_class = 'DBIx::Class::Storage'.$storage_class
453 if $storage_class =~ m/^::/;
8ef144ff 454 eval "require ${storage_class};";
bc0c9800 455 $self->throw_exception(
456 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
457 ) if $@;
82cc0386 458 my $storage = $storage_class->new($self);
66d9ef6b 459 $storage->connect_info(\@info);
460 $self->storage($storage);
461 return $self;
462}
463
87c4e602 464=head2 connect
465
27f01d1f 466=over 4
467
ebc77b53 468=item Arguments: @info
66d9ef6b 469
d601dc88 470=item Return Value: $new_schema
27f01d1f 471
472=back
82b01c38 473
474This is a convenience method. It is equivalent to calling
475$schema->clone->connection(@info). See L</connection> and L</clone> for more
476information.
66d9ef6b 477
478=cut
479
08b515f1 480sub connect { shift->clone->connection(@_) }
481
4012acd8 482=head2 txn_do
08b515f1 483
4012acd8 484=over 4
08b515f1 485
4012acd8 486=item Arguments: C<$coderef>, @coderef_args?
08b515f1 487
4012acd8 488=item Return Value: The return value of $coderef
08b515f1 489
4012acd8 490=back
08b515f1 491
4012acd8 492Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
493returning its result (if any). Equivalent to calling $schema->storage->txn_do.
494See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 495
4012acd8 496This interface is preferred over using the individual methods L</txn_begin>,
497L</txn_commit>, and L</txn_rollback> below.
08b515f1 498
4012acd8 499=cut
08b515f1 500
4012acd8 501sub txn_do {
502 my $self = shift;
08b515f1 503
4012acd8 504 $self->storage or $self->throw_exception
505 ('txn_do called on $schema without storage');
08b515f1 506
4012acd8 507 $self->storage->txn_do(@_);
508}
08b515f1 509
4012acd8 510=head2 txn_begin
a62cf8d4 511
4012acd8 512Begins a transaction (does nothing if AutoCommit is off). Equivalent to
513calling $schema->storage->txn_begin. See
514L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
27f01d1f 515
4012acd8 516=cut
82b01c38 517
4012acd8 518sub txn_begin {
519 my $self = shift;
27f01d1f 520
4012acd8 521 $self->storage or $self->throw_exception
522 ('txn_begin called on $schema without storage');
a62cf8d4 523
4012acd8 524 $self->storage->txn_begin;
525}
a62cf8d4 526
4012acd8 527=head2 txn_commit
a62cf8d4 528
4012acd8 529Commits the current transaction. Equivalent to calling
530$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
531for more information.
a62cf8d4 532
4012acd8 533=cut
a62cf8d4 534
4012acd8 535sub txn_commit {
536 my $self = shift;
a62cf8d4 537
4012acd8 538 $self->storage or $self->throw_exception
539 ('txn_commit called on $schema without storage');
a62cf8d4 540
4012acd8 541 $self->storage->txn_commit;
542}
70634260 543
4012acd8 544=head2 txn_rollback
a62cf8d4 545
4012acd8 546Rolls back the current transaction. Equivalent to calling
547$schema->storage->txn_rollback. See
548L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
a62cf8d4 549
550=cut
551
4012acd8 552sub txn_rollback {
553 my $self = shift;
a62cf8d4 554
19630353 555 $self->storage or $self->throw_exception
4012acd8 556 ('txn_rollback called on $schema without storage');
a62cf8d4 557
4012acd8 558 $self->storage->txn_rollback;
a62cf8d4 559}
560
66d9ef6b 561=head2 clone
562
27f01d1f 563=over 4
564
d601dc88 565=item Return Value: $new_schema
27f01d1f 566
567=back
82b01c38 568
66d9ef6b 569Clones the schema and its associated result_source objects and returns the
570copy.
571
572=cut
573
574sub clone {
575 my ($self) = @_;
04786a4c 576 my $clone = { (ref $self ? %$self : ()) };
577 bless $clone, (ref $self || $self);
578
66d9ef6b 579 foreach my $moniker ($self->sources) {
580 my $source = $self->source($moniker);
581 my $new = $source->new($source);
582 $clone->register_source($moniker => $new);
583 }
82cc0386 584 $clone->storage->set_schema($clone) if $clone->storage;
66d9ef6b 585 return $clone;
586}
587
87c4e602 588=head2 populate
589
27f01d1f 590=over 4
591
ebc77b53 592=item Arguments: $moniker, \@data;
27f01d1f 593
594=back
a37a4697 595
596Populates the source registered with the given moniker with the supplied data.
82b01c38 597@data should be a list of listrefs -- the first containing column names, the
598second matching values.
599
600i.e.,
a37a4697 601
24d67825 602 $schema->populate('Artist', [
603 [ qw/artistid name/ ],
604 [ 1, 'Popular Band' ],
605 [ 2, 'Indie Band' ],
a62cf8d4 606 ...
607 ]);
a37a4697 608
609=cut
610
611sub populate {
612 my ($self, $name, $data) = @_;
613 my $rs = $self->resultset($name);
614 my @names = @{shift(@$data)};
84e3c114 615 my @created;
a37a4697 616 foreach my $item (@$data) {
617 my %create;
618 @create{@names} = @$item;
84e3c114 619 push(@created, $rs->create(\%create));
a37a4697 620 }
84e3c114 621 return @created;
a37a4697 622}
623
82cc0386 624=head2 exception_action
625
626=over 4
627
628=item Arguments: $code_reference
629
630=back
631
db5dc233 632If C<exception_action> is set for this class/object, L</throw_exception>
633will prefer to call this code reference with the exception as an argument,
634rather than its normal <croak> action.
635
636Your subroutine should probably just wrap the error in the exception
637object/class of your choosing and rethrow. If, against all sage advice,
638you'd like your C<exception_action> to suppress a particular exception
639completely, simply have it return true.
82cc0386 640
641Example:
642
643 package My::Schema;
644 use base qw/DBIx::Class::Schema/;
645 use My::ExceptionClass;
646 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
647 __PACKAGE__->load_classes;
648
db5dc233 649 # or:
82cc0386 650 my $schema_obj = My::Schema->connect( .... );
651 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
652
db5dc233 653 # suppress all exceptions, like a moron:
654 $schema_obj->exception_action(sub { 1 });
655
5160b401 656=head2 throw_exception
701da8c4 657
75d07914 658=over 4
82b01c38 659
ebc77b53 660=item Arguments: $message
82b01c38 661
662=back
663
664Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 665user's perspective. See L</exception_action> for details on overriding
666this method's behavior.
701da8c4 667
668=cut
669
670sub throw_exception {
82cc0386 671 my $self = shift;
db5dc233 672 croak @_ if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 673}
674
ec6704d4 675=head2 deploy (EXPERIMENTAL)
1c339d71 676
82b01c38 677=over 4
678
ebc77b53 679=item Arguments: $sqlt_args
82b01c38 680
681=back
682
683Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 684
685Note that this feature is currently EXPERIMENTAL and may not work correctly
686across all databases, or fully handle complex relationships.
1c339d71 687
51bace1c 688See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
689common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
690produced include a DROP TABLE statement for each table created.
691
1c339d71 692=cut
693
694sub deploy {
cb561d1a 695 my ($self, $sqltargs) = @_;
1c339d71 696 $self->throw_exception("Can't deploy without storage") unless $self->storage;
cb561d1a 697 $self->storage->deploy($self, undef, $sqltargs);
1c339d71 698}
699
c0f61310 700=head2 create_ddl_dir (EXPERIMENTAL)
701
702=over 4
703
704=item Arguments: \@databases, $version, $directory, $sqlt_args
705
706=back
707
708Creates an SQL file based on the Schema, for each of the specified
709database types, in the given directory.
710
711Note that this feature is currently EXPERIMENTAL and may not work correctly
712across all databases, or fully handle complex relationships.
713
714=cut
715
e673f011 716sub create_ddl_dir
717{
718 my $self = shift;
719
720 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
721 $self->storage->create_ddl_dir($self, @_);
722}
723
9b83fccd 724=head2 ddl_filename (EXPERIMENTAL)
725
726 my $filename = $table->ddl_filename($type, $dir, $version)
727
728Creates a filename for a SQL file based on the table class name. Not
729intended for direct end user use.
730
731=cut
732
e673f011 733sub ddl_filename
734{
735 my ($self, $type, $dir, $version) = @_;
736
737 my $filename = ref($self);
9e7b9292 738 $filename =~ s/::/-/;
e673f011 739 $filename = "$dir$filename-$version-$type.sql";
740
741 return $filename;
742}
743
a02675cd 7441;
c2da098a 745
c2da098a 746=head1 AUTHORS
747
daec44b8 748Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 749
750=head1 LICENSE
751
752You may distribute this code under the same terms as Perl itself.
753
754=cut
755