Subject: | Per-source generated routines cache the resultset |
Date: | Thu, 7 Aug 2014 19:37:38 +0000 |
To: | bugs-Test-DBIx-Class [...] rt.cpan.org |
From: | Matt S Trout <mst [...] shadowcat.co.uk> |
19:49 < lejeunerenard> Question: I'm getting an 'execute failed: database table is locked' error when deleting a row from my shared cache in memory SQLite db. I am not sure what's got the lock on the db.
19:49 < lejeunerenard> Background: Testing a Dancer app with Test::DBIx::Class. Just testing the delete route for my model. Both Dancer and Test::DBIx::Class are configured with 'dbi:SQLite:dbname=share/test.db'. Maybe the two are conflicting?
19:51 < mst> 'database is locked' can mean 'you have an open $sth'
19:52 < mst> i.e. you're probably better using $rs->all instead of $rs->next
20:25 < mst> the bug is that you're doing e.g. User->first->id
20:25 < mst> and now you have two users, that is fail
20:25 < mst> however, that shouldn't fail
20:25 < mst> feel like trying a small patch against Test::DBIx::Class ?
20:25 < lejeunerenard> mst: sure
20:25 < mst> ok, so, crack open your Test/DBIx/Class.pm
20:25 < lejeunerenard> yep
20:26 < mst> if you look near the bottom of the import() method
20:26 < mst> there's a 'map' across $schema->sources
20:26 < mst> that returns a sub {}
20:26 < mst> whose last line is 'return $resultset;'
20:26 < mst> right?
20:26 < lejeunerenard> right
20:26 < mst> change it to 'return $resultset->search_rs;'
20:27 < purl> mst: that doesn't look right
20:27 < mst> and then see if your test works
20:27 < skaufman> jnap: hey i was thinking of adding a feature or two to DBIx::Class::Fixtures
20:27 < skaufman> is it a pain to get it to github?
20:28 < skaufman> i already cloned it from where it is now, so i can submit a patch or whatever as well
20:28 < lejeunerenard> mst: shit. it works
20:28 < lejeunerenard> but why?
20:28 < mst> because it was exactly what I told you it was
20:28 < mst> 19:51 < mst> 'database is locked' can mean 'you have an open $sth'
20:28 < mst> 19:52 < mst> i.e. you're probably better using $rs->all instead of $rs->next
20:29 < mst> you called ->first, which did a SELECT * on the table, then returned the first row
20:29 < mst> once you had TWO rows, that sth was incomplete
20:29 < mst> which meant the database stayed locked
20:29 < mst> that patch makes Event() return a new resultset every time
20:29 < mst> so it goes out of scope and the sth goes away
20:30 < mst> you would, btw, also find that
20:30 < mst> my $event = Event->next;
20:30 < mst> my $event2 = Event->next;
20:30 < mst> would, rather confusingly, give you each row in order
20:30 < lejeunerenard> mst: oh ok. didnt realize that first would leave a sth hanging like that.
20:30 < mst> it shouldn't
20:30 < lejeunerenard> mst: is that from my code?
20:30 < mst> it's from Test::DBIx::Class accidentally caching $resultset
20:30 -!- Vandal [~Vandal@176.209.251.172] has quit [Quit: Any sufficiently advanced technology is indistinguishable from magic. (Arthur C. Clarke)]
20:31 < mst> and forgetting that it's both a 'thing' and an iterator
20:31 < mst> (design error on my part in 2005, never mind)
20:31 < mst> so the ->search_rs does a copy, so you get a new resultset every time you call Event
20:31 < mst> so you don't accidentally share iteration state
20:31 < mst> we had the same bug in Catalyst::Model::DBIC::Schema some time in 2006 or '07 IIRC, too
--
Matt S Trout - Shadowcat Systems - Perl consulting with a commit bit and a clue
http://shadowcat.co.uk/blog/matt-s-trout/ http://twitter.com/shadowcat_mst/
Email me now on mst (at) shadowcat.co.uk and let's chat about how our CPAN
commercial support, training and consultancy packages could help your team.