Merge 'trunk' into 'DBIx-Class-current'
Justin Guenther [Thu, 25 May 2006 14:53:12 +0000 (07:53 -0700)]
r1808@moss (orig r1807):  jguenther | 2006-05-25 09:53:12 -0700
Changed txn_do docs/Cookbook example to use closures, and made their content more consistent

1  2 
lib/DBIx/Class/Manual/Cookbook.pod
lib/DBIx/Class/Schema.pm

@@@ -409,24 -409,22 +409,22 @@@ example of the recommended way to use i
  
    my $genus = $schema->resultset('Genus')->find(12);
  
+   my $coderef2 = sub {
+     $genus->extinct(1);
+     $genus->update;
+   };
    my $coderef1 = sub {
      $genus->add_to_species({ name => 'troglodyte' });
      $genus->wings(2);
      $genus->update;
-     $schema->txn_do($code, $genus); # Can have a nested transaction
+     $schema->txn_do($coderef2); # Can have a nested transaction
      return $genus->species;
    };
  
-   my $coderef2 = sub {
-     my ($genus) = @_;
-     $genus->extinct(1);
-     $genus->update;
-   };
    my $rs;
    eval {
-     $rs = $schema->txn_do($coderef1, $schema, $genus, $coderef2);
+     $rs = $schema->txn_do($coderef1);
    };
  
    if ($@) {                             # Transaction failed
@@@ -785,66 -783,6 +783,66 @@@ It is possible to get a Schema object f
  This can be useful when you don't want to pass around a Schema object to every
  method.
  
 +=head2 Profiling
 +
 +When you enable L<DBIx::Class::Storage::DBI>'s debugging it prints the SQL
 +executed as well as notifications of query completion and transaction
 +begin/commit.  If you'd like to profile the SQL you can subclass the
 +L<DBIx::Class::Storage::Statistics> class and write your own profiling
 +mechanism:
 +
 +  package My::Profiler;
 +  use strict;
 +
 +  use base 'DBIx::Class::Storage::Statistics';
 +
 +  use Time::HiRes qw(time);
 +
 +  my $start;
 +
 +  sub query_start {
 +    my $self = shift();
 +    my $sql = shift();
 +    my $params = @_;
 +
 +    print "Executing $sql: ".join(', ', @params)."\n";
 +    $start = time();
 +  }
 +
 +  sub query_end {
 +    my $self = shift();
 +    my $sql = shift();
 +    my @params = @_;
 +
 +    printf("Execution took %0.4f seconds.\n", time() - $start);
 +    $start = undef;
 +  }
 +
 +  1;
 +
 +You can then install that class as the debugging object:
 +
 +  __PACKAGE__->storage()->debugobj(new My::Profiler());
 +  __PACKAGE__->storage()->debug(1);
 +
 +A more complicated example might involve storing each execution of SQL in an
 +array:
 +
 +  sub query_end {
 +    my $self = shift();
 +    my $sql = shift();
 +    my @params = @_;
 +
 +    my $elapsed = time() - $start;
 +    push(@{ $calls{$sql} }, {
 +        params => \@params,
 +        elapsed => $elapsed
 +    });
 +  }
 +
 +You could then create average, high and low execution times for an SQL
 +statement and dig down to see if certain parameters cause aberrant behavior.
 +
  =head2 Getting the value of the primary key for the last database insert
  
  AKA getting last_insert_id
diff --combined lib/DBIx/Class/Schema.pm
@@@ -21,7 -21,7 +21,7 @@@ DBIx::Class::Schema - composable schema
  
    package Library::Schema;
    use base qw/DBIx::Class::Schema/;
 -  
 +
    # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
    __PACKAGE__->load_classes(qw/CD Book DVD/);
  
@@@ -37,7 -37,7 +37,7 @@@
      $password,
      { AutoCommit => 0 },
    );
 -  
 +
    my $schema2 = Library::Schema->connect($coderef_returning_dbh);
  
    # fetch objects using Library::Schema::DVD
@@@ -221,15 -221,15 +221,15 @@@ Example
  
  sub load_classes {
    my ($class, @params) = @_;
 -  
 +
    my %comps_for;
 -  
 +
    if (@params) {
      foreach my $param (@params) {
        if (ref $param eq 'ARRAY') {
          # filter out commented entries
          my @modules = grep { $_ !~ /^#/ } @$param;
 -        
 +
          push (@{$comps_for{$class}}, @modules);
        }
        elsif (ref $param eq 'HASH') {
      foreach my $prefix (keys %comps_for) {
        foreach my $comp (@{$comps_for{$prefix}||[]}) {
          my $comp_class = "${prefix}::${comp}";
 -        eval "use $comp_class"; # If it fails, assume the user fixed it
 -        if ($@) {
 -          $comp_class =~ s/::/\//g;
 -          die $@ unless $@ =~ /Can't locate.+$comp_class\.pm\sin\s\@INC/;
 -          warn $@ if $@;
 -        }
 -        push(@to_register, [ $comp, $comp_class ]);
 +        $class->ensure_class_loaded($comp_class);
 +        $comp_class->source_name($comp) unless $comp_class->source_name;
 +
 +        push(@to_register, [ $comp_class->source_name, $comp_class ]);
        }
      }
    }
@@@ -522,12 -525,11 +522,11 @@@ exception) an exception is thrown that 
  For example,
  
    my $author_rs = $schema->resultset('Author')->find(1);
+   my @titles = qw/Night Day It/;
  
    my $coderef = sub {
-     my ($author, @titles) = @_;
      # If any one of these fails, the entire transaction fails
-     $author->create_related('books', {
+     $author_rs->create_related('books', {
        title => $_
      }) foreach (@titles);
  
  
    my $rs;
    eval {
-     $rs = $schema->txn_do($coderef, $author_rs, qw/Night Day It/);
+     $rs = $schema->txn_do($coderef);
    };
  
-   if ($@) {
-     my $error = $@;
-     if ($error =~ /Rollback failed/) {
-       die "something terrible has happened!";
-     } else {
-       deal_with_failed_transaction();
-     }
+   if ($@) {                                  # Transaction failed
+     die "something terrible has happened!"   #
+       if ($@ =~ /Rollback failed/);          # Rollback failed
+     deal_with_failed_transaction();
    }
  
  In a nested transaction (calling txn_do() from within a txn_do() coderef) only
@@@ -710,41 -710,6 +707,41 @@@ sub deploy 
    $self->storage->deploy($self, undef, $sqltargs);
  }
  
 +=head2 create_ddl_dir (EXPERIMENTAL)
 +
 +=over 4
 +
 +=item Arguments: \@databases, $version, $directory, $sqlt_args
 +
 +=back
 +
 +Creates an SQL file based on the Schema, for each of the specified
 +database types, in the given directory.
 +
 +Note that this feature is currently EXPERIMENTAL and may not work correctly
 +across all databases, or fully handle complex relationships.
 +
 +=cut
 +
 +sub create_ddl_dir
 +{
 +  my $self = shift;
 +
 +  $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
 +  $self->storage->create_ddl_dir($self, @_);
 +}
 +
 +sub ddl_filename
 +{
 +    my ($self, $type, $dir, $version) = @_;
 +
 +    my $filename = ref($self);
 +    $filename =~ s/^.*:://;
 +    $filename = "$dir$filename-$version-$type.sql";
 +
 +    return $filename;
 +}
 +
  1;
  
  =head1 AUTHORS