Split out the upper half of S::DBI::_execute for easier inheritance
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / Schema.pm
index 3103d29..ee4b936 100644 (file)
@@ -285,16 +285,16 @@ sub load_classes {
 =back
 
 This is an alternative to L</load_classes> above which assumes an alternative
-layout for automatic class loading.  It assumes that all source-definition
-classes are underneath a sub-namespace of the schema called C<Source>, any
+layout for automatic class loading.  It assumes that all result
+classes are underneath a sub-namespace of the schema called C<Result>, any
 corresponding ResultSet classes are underneath a sub-namespace of the schema
 called C<ResultSet>.
 
 Both of the sub-namespaces are configurable if you don't like the defaults,
-via the options C<source_namespace> and C<resultset_namespace>.
+via the options C<result_namespace> and C<resultset_namespace>.
 
 If (and only if) you specify the option C<default_resultset_class>, any found
-source-definition classes for which we do not find a corresponding
+Result classes for which we do not find a corresponding
 ResultSet class will have their C<resultset_class> set to
 C<default_resultset_class>.
 
@@ -307,34 +307,34 @@ it with a literal C<+>.
 
 Examples:
 
-  # load My::Schema::Source::CD, My::Schema::Source::Artist,
+  # load My::Schema::Result::CD, My::Schema::Result::Artist,
   #    My::Schema::ResultSet::CD, etc...
   My::Schema->load_namespaces;
 
-  # Override everything...
+  # Override everything to use ugly names.
+  # In this example, if there is a My::Schema::Res::Foo, but no matching
+  #   My::Schema::RSets::Foo, then Foo will have its
+  #   resultset_class set to My::Schema::RSetBase
   My::Schema->load_namespaces(
-    source_namespace => 'Srcs',
+    result_namespace => 'Res',
     resultset_namespace => 'RSets',
     default_resultset_class => 'RSetBase',
   );
-  # In the above, if there is a My::Schema::Srcs::Foo, but no matching
-  #   My::Schema::RSets::Foo, then the Foo source will have its
-  #   resultset_class set to My::Schema::RSetBase
 
   # Put things in other namespaces
   My::Schema->load_namespaces(
-    source_namespace => '+Some::Place::Sources',
+    result_namespace => '+Some::Place::Results',
     resultset_namespace => '+Another::Place::RSets',
   );
 
 If you'd like to use multiple namespaces of each type, simply use an arrayref
-of namespaces for that option.  In the case that the same source-definition
+of namespaces for that option.  In the case that the same result
 (or resultset) class exists in multiple namespaces, the latter entries in
 your list of namespaces will override earlier ones.
 
   My::Schema->load_namespaces(
-    # My::Schema::Sources_C::Foo takes precedence over My::Schema::Sources_B::Foo :
-    source_namespace => [ 'Sources_A', 'Sources_B', 'Sources_C' ],
+    # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
+    result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
     resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
   );
 
@@ -371,7 +371,7 @@ sub _map_namespaces {
 sub load_namespaces {
   my ($class, %args) = @_;
 
-  my $source_namespace = delete $args{source_namespace} || 'Source';
+  my $result_namespace = delete $args{result_namespace} || 'Result';
   my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
   my $default_resultset_class = delete $args{default_resultset_class};
 
@@ -382,7 +382,7 @@ sub load_namespaces {
   $default_resultset_class
     = $class->_expand_relative_name($default_resultset_class);
 
-  for my $arg ($source_namespace, $resultset_namespace) {
+  for my $arg ($result_namespace, $resultset_namespace) {
     $arg = [ $arg ] if !ref($arg) && $arg;
 
     $class->throw_exception('load_namespaces: namespace arguments must be '
@@ -392,7 +392,7 @@ sub load_namespaces {
     $_ = $class->_expand_relative_name($_) for (@$arg);
   }
 
-  my %sources = $class->_map_namespaces(@$source_namespace);
+  my %results = $class->_map_namespaces(@$result_namespace);
   my %resultsets = $class->_map_namespaces(@$resultset_namespace);
 
   my @to_register;
@@ -401,31 +401,31 @@ sub load_namespaces {
     local *Class::C3::reinitialize = sub { };
     use warnings 'redefine';
 
-    foreach my $source (keys %sources) {
-      my $source_class = $sources{$source};
-      $class->ensure_class_loaded($source_class);
-      $source_class->source_name($source) unless $source_class->source_name;
+    foreach my $result (keys %results) {
+      my $result_class = $results{$result};
+      $class->ensure_class_loaded($result_class);
+      $result_class->source_name($result) unless $result_class->source_name;
 
-      my $rs_class = delete $resultsets{$source};
-      my $rs_set = $source_class->resultset_class;
+      my $rs_class = delete $resultsets{$result};
+      my $rs_set = $result_class->resultset_class;
       if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
         if($rs_class && $rs_class ne $rs_set) {
-          warn "We found ResultSet class '$rs_class' for '$source', but it seems "
-             . "that you had already set '$source' to use '$rs_set' instead";
+          warn "We found ResultSet class '$rs_class' for '$result', but it seems "
+             . "that you had already set '$result' to use '$rs_set' instead";
         }
       }
       elsif($rs_class ||= $default_resultset_class) {
         $class->ensure_class_loaded($rs_class);
-        $source_class->resultset_class($rs_class);
+        $result_class->resultset_class($rs_class);
       }
 
-      push(@to_register, [ $source_class->source_name, $source_class ]);
+      push(@to_register, [ $result_class->source_name, $result_class ]);
     }
   }
 
   foreach (sort keys %resultsets) {
     warn "load_namespaces found ResultSet class $_ with no "
-      . 'corresponding source-definition class';
+      . 'corresponding Result class';
   }
 
   Class::C3->reinitialize;
@@ -593,8 +593,10 @@ sub setup_connection_class {
 
 Instantiates a new Storage object of type
 L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
-$storage->connect_info. Sets the connection in-place on the schema. See
-L<DBIx::Class::Storage::DBI/"connect_info"> for more information.
+$storage->connect_info. Sets the connection in-place on the schema.
+
+See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
+or L<DBIx::Class::Storage> in general.
 
 =cut
 
@@ -632,138 +634,83 @@ information.
 
 sub connect { shift->clone->connection(@_) }
 
-=head2 txn_begin
-
-Begins a transaction (does nothing if AutoCommit is off). Equivalent to
-calling $schema->storage->txn_begin. See
-L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
+=head2 txn_do
 
-=cut
+=over 4
 
-sub txn_begin { shift->storage->txn_begin }
+=item Arguments: C<$coderef>, @coderef_args?
 
-=head2 txn_commit
+=item Return Value: The return value of $coderef
 
-Commits the current transaction. Equivalent to calling
-$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
-for more information.
+=back
 
-=cut
+Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
+returning its result (if any). Equivalent to calling $schema->storage->txn_do.
+See L<DBIx::Class::Storage/"txn_do"> for more information.
 
-sub txn_commit { shift->storage->txn_commit }
+This interface is preferred over using the individual methods L</txn_begin>,
+L</txn_commit>, and L</txn_rollback> below.
 
-=head2 txn_rollback
+=cut
 
-Rolls back the current transaction. Equivalent to calling
-$schema->storage->txn_rollback. See
-L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
+sub txn_do {
+  my $self = shift;
 
-=cut
+  $self->storage or $self->throw_exception
+    ('txn_do called on $schema without storage');
 
-sub txn_rollback { shift->storage->txn_rollback }
+  $self->storage->txn_do(@_);
+}
 
-=head2 txn_do
+=head2 txn_begin
 
-=over 4
+Begins a transaction (does nothing if AutoCommit is off). Equivalent to
+calling $schema->storage->txn_begin. See
+L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
 
-=item Arguments: C<$coderef>, @coderef_args?
+=cut
 
-=item Return Value: The return value of $coderef
+sub txn_begin {
+  my $self = shift;
 
-=back
+  $self->storage or $self->throw_exception
+    ('txn_begin called on $schema without storage');
 
-Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
-returning its result (if any). If an exception is caught, a rollback is issued
-and the exception is rethrown. If the rollback fails, (i.e. throws an
-exception) an exception is thrown that includes a "Rollback failed" message.
+  $self->storage->txn_begin;
+}
 
-For example,
+=head2 txn_commit
 
-  my $author_rs = $schema->resultset('Author')->find(1);
-  my @titles = qw/Night Day It/;
+Commits the current transaction. Equivalent to calling
+$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
+for more information.
 
-  my $coderef = sub {
-    # If any one of these fails, the entire transaction fails
-    $author_rs->create_related('books', {
-      title => $_
-    }) foreach (@titles);
+=cut
 
-    return $author->books;
-  };
+sub txn_commit {
+  my $self = shift;
 
-  my $rs;
-  eval {
-    $rs = $schema->txn_do($coderef);
-  };
+  $self->storage or $self->throw_exception
+    ('txn_commit called on $schema without storage');
 
-  if ($@) {                                  # Transaction failed
-    die "something terrible has happened!"   #
-      if ($@ =~ /Rollback failed/);          # Rollback failed
+  $self->storage->txn_commit;
+}
 
-    deal_with_failed_transaction();
-  }
+=head2 txn_rollback
 
-In a nested transaction (calling txn_do() from within a txn_do() coderef) only
-the outermost transaction will issue a L<DBIx::Class::Schema/"txn_commit"> on
-the Schema's storage, and txn_do() can be called in void, scalar and list
-context and it will behave as expected.
+Rolls back the current transaction. Equivalent to calling
+$schema->storage->txn_rollback. See
+L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
 
 =cut
 
-sub txn_do {
-  my ($self, $coderef, @args) = @_;
+sub txn_rollback {
+  my $self = shift;
 
   $self->storage or $self->throw_exception
-    ('txn_do called on $schema without storage');
-  ref $coderef eq 'CODE' or $self->throw_exception
-    ('$coderef must be a CODE reference');
-
-  my (@return_values, $return_value);
-
-  $self->txn_begin; # If this throws an exception, no rollback is needed
-
-  my $wantarray = wantarray; # Need to save this since the context
-                             # inside the eval{} block is independent
-                             # of the context that called txn_do()
-  eval {
-
-    # Need to differentiate between scalar/list context to allow for
-    # returning a list in scalar context to get the size of the list
-    if ($wantarray) {
-      # list context
-      @return_values = $coderef->(@args);
-    } elsif (defined $wantarray) {
-      # scalar context
-      $return_value = $coderef->(@args);
-    } else {
-      # void context
-      $coderef->(@args);
-    }
-    $self->txn_commit;
-  };
-
-  if ($@) {
-    my $error = $@;
+    ('txn_rollback called on $schema without storage');
 
-    eval {
-      $self->txn_rollback;
-    };
-
-    if ($@) {
-      my $rollback_error = $@;
-      my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
-      $self->throw_exception($error)  # propagate nested rollback
-        if $rollback_error =~ /$exception_class/;
-
-      $self->throw_exception(
-        "Transaction aborted: $error. Rollback failed: ${rollback_error}"
-      );
-    } else {
-      $self->throw_exception($error); # txn failed but rollback succeeded
-    }
-  }
-
-  return $wantarray ? @return_values : $return_value;
+  $self->storage->txn_rollback;
 }
 
 =head2 clone
@@ -781,7 +728,9 @@ copy.
 
 sub clone {
   my ($self) = @_;
-  my $clone = bless({ (ref $self ? %$self : ()) }, ref $self || $self);
+  my $clone = { (ref $self ? %$self : ()) };
+  bless $clone, (ref $self || $self);
+
   foreach my $moniker ($self->sources) {
     my $source = $self->source($moniker);
     my $new = $source->new($source);
@@ -882,7 +831,7 @@ sub throw_exception {
 
 =over 4
 
-=item Arguments: $sqlt_args
+=item Arguments: $sqlt_args, $dir
 
 =back
 
@@ -898,9 +847,9 @@ produced include a DROP TABLE statement for each table created.
 =cut
 
 sub deploy {
-  my ($self, $sqltargs) = @_;
+  my ($self, $sqltargs, $dir) = @_;
   $self->throw_exception("Can't deploy without storage") unless $self->storage;
-  $self->storage->deploy($self, undef, $sqltargs);
+  $self->storage->deploy($self, undef, $sqltargs, $dir);
 }
 
 =head2 create_ddl_dir (EXPERIMENTAL)
@@ -919,8 +868,7 @@ across all databases, or fully handle complex relationships.
 
 =cut
 
-sub create_ddl_dir
-{
+sub create_ddl_dir {
   my $self = shift;
 
   $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
@@ -936,8 +884,7 @@ intended for direct end user use.
 
 =cut
 
-sub ddl_filename
-{
+sub ddl_filename {
     my ($self, $type, $dir, $version) = @_;
 
     my $filename = ref($self);
@@ -958,4 +905,3 @@ Matt S. Trout <mst@shadowcatsystems.co.uk>
 You may distribute this code under the same terms as Perl itself.
 
 =cut
-