Prevent SQL::Translator::Producer::YAML from seeing our potential $dbh
authorPeter Rabbitson <ribasushi@cpan.org>
Sat, 16 Feb 2013 15:27:23 +0000 (16:27 +0100)
committerPeter Rabbitson <ribasushi@cpan.org>
Mon, 18 Feb 2013 18:37:08 +0000 (19:37 +0100)
commit31399b48455c44ca45cc1e143ae58ef0a55ce2ff
tree49ec038fd0dae5c52292dc13241830df1c128f34
parenta07ae2aaf50887b2e84dd391fae1558d01c39f15
Prevent SQL::Translator::Producer::YAML from seeing our potential $dbh

The failure mode here is extremely convoluted, full of unimaginable fail
and makes baby jesus cry :(

The long story: there are two ways to supply a $schema to the SQLT producer:
via an argument to translate() (sane) or at the time of translator instance
creation (less sane). In the second case this becomes a problem because some
serializing producers (e.g. SQLT::Producer::YAML) take the *entire*
SQLT instance and dump it to YAML. This includes the arguments which include
our schema with its storage and potentially its $dbh. This causes the
weird warnings described in e.g. RT#75394, because YAML creates a dead
DBI object upon de-serialization of said arguments. What's even more sad is
that while the YAML Producer dumps the entire SQLT instance, the YAML Parser
simply takes the ->{schema} part of this structure and throws everything
else away.

Of course we can not just fix the ::Producer - folks may very well be relying
on the structure it spits out (nobody knows if the *only* consumer of the
Producer::YAML output is in fact Parser::YAML). Really the only thing we can
know (well not know, but reasonably assume) is that there is no way that any
user relies on the accessing the storage passed in with a schema instance to
be parsed.

So what we do is the least invasive thing of all - at translate() time we
check the state of the passed in $schema and if it does have a storage
instance we simply detach it (by cloning the $schema instance) and as a
result everything remains happy.
Changes
lib/SQL/Translator/Parser/DBIx/Class.pm
t/99dbic_sqlt_parser.t