From perlfunc:
do 'stat.pl';
is just like
eval `cat stat.pl`;
So when you do 'foo.pl'
, you execute the code in the current context. Because I don't know what goes on in foo.pl
or Foo.pm
, I can't tell you what's changed. But, I can tell you that it's always executed in the current context, and now in executes in Foo::
namespace.
The way you're calling this, you are passing 'Foo'
as the first parameter to Foo::connect
or the returned sub from Foo->can('connect')
. It seems that somehow that's being passed to some code that thinks it's a database handle, and that's telling that object to rollback
.
Probably not. Your SQL generation code takes the wrong approach. You are hiding too much information from your program. At some point, your program knows which table to select from. Instead of throwing that information away and embedding it inside an opaque SQL command, you should keep it around. Then your logger function doesn't have to guess where the log data should go; it knows.
Maybe this is clearer with some code. Your code looks like:
sub make_query {
my ($table, $columns, $conditions) = @_;
return "SELECT $columns FROM $table WHERE $conditions";
}
sub run_query {
my ($query) = @_;
$dbh->prepare($query);
...
}
run_query( make_query( 'foo', '*', '1=1' ) );
This doesn't let you do what you want to do. So you should structure
your program to do something like:
sub make_query {
my ($table, $columns, $conditions) = @_;
return +{
query => "SELECT $columns FROM $table WHERE $conditions",
table => $table,
} # an object might not be a bad idea
}
sub run_query {
my ($query) = @_;
$dbh->prepare($query->{query});
log_to_file( $query->{table}.'.log', ... );
...
}
run_query( make_query( 'foo', '*', '1=1' ) );
The API is the same, but now you have the information you need to log
the way you want.
Also, consider SQL::Abstract for dynamic SQL generation. My code
above is just an example.
Edit: OK, so you say you're using SQLite. It has an EXPLAIN command
which you could parse the output of:
sqlite> explain select * from test;
0|Trace|0|0|0|explain select * from test;|00|
1|Goto|0|11|0||00|
2|SetNumColumns|0|2|0||00|
3|OpenRead|0|2|0||00|
4|Rewind|0|9|0||00|
5|Column|0|0|1||00|
6|Column|0|1|2||00|
7|ResultRow|1|2|0||00|
8|Next|0|5|0||00|
9|Close|0|0|0||00|
10|Halt|0|0|0||00|
11|Transaction|0|0|0||00|
12|VerifyCookie|0|1|0||00|
13|TableLock|0|2|0|test|00|
14|Goto|0|2|0||00|
Looks like TableLock is what you would want to look for. YMMV, this
is a bad idea.
Best Answer
It's worth noting that if you're running a version of DBD::mysql new enough (3.0008 on), you can do the following:
$dbh->{'mysql_enable_utf8'} = 1;
and then everything's decode()ed/encode()ed for you on the way out from/in to DBI.