Merge 'trunk' into 'mssql_limit_regression'
Peter Rabbitson [Sat, 9 Jan 2010 10:39:35 +0000 (10:39 +0000)]
r8277@Thesaurus (orig r8265):  ribasushi | 2010-01-09 02:16:14 +0100
 r8263@Thesaurus (orig r8251):  ribasushi | 2010-01-08 15:43:38 +0100
 New branch to find a leak
 r8264@Thesaurus (orig r8252):  ribasushi | 2010-01-08 15:52:46 +0100
 Weird test failures
 r8272@Thesaurus (orig r8260):  ribasushi | 2010-01-09 01:24:56 +0100
 Proper invocation
 r8273@Thesaurus (orig r8261):  ribasushi | 2010-01-09 01:35:34 +0100
 Test for the real leak reason
 r8274@Thesaurus (orig r8262):  ribasushi | 2010-01-09 01:37:33 +0100
 Void ctx as it should be
 r8275@Thesaurus (orig r8263):  ribasushi | 2010-01-09 02:10:13 +0100
 A "fix" for sqlt-related schema leaks
 r8276@Thesaurus (orig r8264):  ribasushi | 2010-01-09 02:15:53 +0100
 Changes

Changes
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/Schema.pm
lib/SQL/Translator/Parser/DBIx/Class.pm
t/52cycle.t
t/99dbic_sqlt_parser.t
t/lib/DBICTest.pm
t/schema/anon.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 73b8c8a..9bc4326 100644 (file)
--- a/Changes
+++ b/Changes
@@ -17,6 +17,7 @@ Revision history for DBIx::Class
           prefetching resultset
         - New MSSQL specific resultset attribute to allow hacky ordered
           subquery suppot
+        - Fix nasty schema/dbhandle leak due to SQL::Translator
 
 0.08115 2009-12-10 09:02:00 (CST)
         - Real limit/offset support for MSSQL server (via Row_Number)
index 541aa12..c3b9c74 100644 (file)
@@ -1583,7 +1583,7 @@ L<DBIx::Class::ResultSourceHandle>.
 =cut
 
 sub handle {
-    return new DBIx::Class::ResultSourceHandle({
+    return DBIx::Class::ResultSourceHandle->new({
         schema         => $_[0]->schema,
         source_moniker => $_[0]->source_name
     });
index e6e09ed..2021151 100644 (file)
@@ -5,7 +5,7 @@ use warnings;
 
 use DBIx::Class::Exception;
 use Carp::Clan qw/^DBIx::Class/;
-use Scalar::Util qw/weaken/;
+use Scalar::Util ();
 use File::Spec;
 use Sub::Name ();
 use Module::Find();
@@ -1295,7 +1295,7 @@ sub _register_source {
 
   $source = $source->new({ %$source, source_name => $moniker });
   $source->schema($self);
-  weaken($source->{schema}) if ref($self);
+  Scalar::Util::weaken($source->{schema}) if ref($self);
 
   my $rs_class = $source->result_class;
 
index 705d380..5d146f8 100644 (file)
@@ -15,6 +15,7 @@ $DEBUG = 0 unless defined $DEBUG;
 use Exporter;
 use SQL::Translator::Utils qw(debug normalize_name);
 use Carp::Clan qw/^SQL::Translator|^DBIx::Class/;
+use Scalar::Util ();
 
 use base qw(Exporter);
 
@@ -30,6 +31,10 @@ use base qw(Exporter);
 # We're working with DBIx::Class Schemas, not data streams.
 # -------------------------------------------------------------------
 sub parse {
+    # this is a hack to prevent schema leaks due to a retarded SQLT implementation
+    # DO NOT REMOVE (until SQLT2 is out, the all of this will be rewritten anyway)
+    Scalar::Util::weaken ($_[1]);
+
     my ($tr, $data)   = @_;
     my $args          = $tr->parser_args;
     my $dbicschema    = $args->{'DBIx::Class::Schema'} ||  $args->{"DBIx::Schema"} ||$data;
index 8be1768..145ad92 100644 (file)
@@ -8,16 +8,36 @@ BEGIN {
   eval { require Test::Memory::Cycle; require Devel::Cycle };
   if ($@ or Devel::Cycle->VERSION < 1.10) {
     plan skip_all => "leak test needs Test::Memory::Cycle and Devel::Cycle >= 1.10";
-  } else {
-    plan tests => 1;
-  }
+  };
 }
 
 use DBICTest;
 use DBICTest::Schema;
+use Scalar::Util ();
 
 import Test::Memory::Cycle;
 
-my $s = DBICTest::Schema->clone;
+my $weak;
 
-memory_cycle_ok($s, 'No cycles in schema');
+{
+  my $s = $weak->{schema} = DBICTest->init_schema;
+  memory_cycle_ok($s, 'No cycles in schema');
+
+  my $rs = $weak->{resultset} = $s->resultset ('Artist');
+  memory_cycle_ok($rs, 'No cycles in resultset');
+
+  my $rsrc = $weak->{resultsource} = $rs->result_source;
+  memory_cycle_ok($rsrc, 'No cycles in resultsource');
+
+  my $row = $weak->{row} = $rs->first;
+  memory_cycle_ok($row, 'No cycles in row');
+
+  Scalar::Util::weaken ($_) for values %$weak;
+  memory_cycle_ok($weak, 'No cycles in weak object collection');
+}
+
+for (keys %$weak) {
+  ok (! $weak->{$_}, "No $_ leaks");
+}
+
+done_testing;
index f8b88c3..4d1ddac 100644 (file)
@@ -5,6 +5,8 @@ use Test::More;
 use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
+use DBICTest::Schema;
+use Scalar::Util ();
 
 BEGIN {
   require DBIx::Class::Storage::DBI;
@@ -13,6 +15,16 @@ BEGIN {
     if not DBIx::Class::Storage::DBI->_sqlt_version_ok;
 }
 
+# Test for SQLT-related leaks
+{
+  my $s = DBICTest::Schema->clone;
+  create_schema ({ schema => $s });
+  Scalar::Util::weaken ($s);
+
+  ok (!$s, 'Schema not leaked');
+}
+
+
 my $schema = DBICTest->init_schema();
 # Dummy was yanked out by the sqlt hook test
 # CustomSql tests the horrific/deprecated ->name(\$sql) hack
index 852d07a..66a79e8 100644 (file)
@@ -127,7 +127,7 @@ sub deploy_schema {
     my $args = shift || {};
 
     if ($ENV{"DBICTEST_SQLT_DEPLOY"}) { 
-        $schema->deploy($args);    
+        $schema->deploy($args);
     } else {
         open IN, "t/lib/sqlite.sql";
         my $sql;
diff --git a/t/schema/anon.t b/t/schema/anon.t
new file mode 100644 (file)
index 0000000..4d74ace
--- /dev/null
@@ -0,0 +1,13 @@
+use strict;
+use warnings;
+use Test::More;
+use Test::Exception;
+
+use lib qw(t/lib);
+use DBICTest;
+
+lives_ok (sub {
+  DBICTest->init_schema()->resultset('Artist')->find({artistid => 1 })->update({name => 'anon test'});
+}, 'Schema object not lost in chaining');
+
+done_testing;