| File | /project/perl/lib/Ima/DBI.pm |
| Statements Executed | 253 |
| Statement Execution Time | 7.06ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 13 | 1 | 1 | 2.04ms | 3.67ms | Ima::DBI::set_sql |
| 8 | 3 | 2 | 392µs | 170ms | Ima::DBI::__ANON__[:316] |
| 13 | 1 | 1 | 380µs | 380µs | Ima::DBI::_mk_sql_closure |
| 2 | 2 | 2 | 245µs | 6.79ms | Ima::DBI::__ANON__[:384] |
| 1 | 1 | 1 | 229µs | 726µs | Ima::DBI::set_db |
| 27 | 3 | 2 | 180µs | 180µs | Ima::DBI::CORE:subst (opcode) |
| 1 | 1 | 1 | 86µs | 255µs | Ima::DBI::_remember_handle |
| 1 | 1 | 1 | 77µs | 197µs | Ima::DBI::_add_default_attributes |
| 2 | 1 | 1 | 51µs | 51µs | Ima::DBI::transform_sql |
| 1 | 1 | 1 | 37µs | 37µs | Ima::DBI::_mk_db_closure |
| 1 | 1 | 1 | 16µs | 16µs | Ima::DBI::_default_attributes |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::BEGIN |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::DBIwarn |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::_croak |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::commit |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::db_handles |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::db_names |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::rollback |
| 0 | 0 | 0 | 0s | 0s | Ima::DBI::sql_names |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Ima::DBI; | ||||
| 2 | |||||
| 3 | 1 | 6µs | $VERSION = '0.34'; | ||
| 4 | |||||
| 5 | 3 | 103µs | 1 | 26µs | use strict; # spent 26µs making 1 call to strict::import |
| 6 | 3 | 89µs | 1 | 0s | use base 'Class::Data::Inheritable'; # spent 271µs making 1 call to base::import, recursion: max depth 4, time 271µs |
| 7 | 3 | 955µs | 1 | 143µs | use DBI; # spent 143µs making 1 call to Exporter::import |
| 8 | |||||
| 9 | # Some class data to store a per-class list of handles. | ||||
| 10 | 1 | 37µs | 1 | 68µs | Ima::DBI->mk_classdata('__Database_Names'); # spent 68µs making 1 call to Class::Data::Inheritable::mk_classdata |
| 11 | 1 | 22µs | 1 | 49µs | Ima::DBI->mk_classdata('__Statement_Names'); # spent 49µs making 1 call to Class::Data::Inheritable::mk_classdata |
| 12 | |||||
| 13 | =head1 NAME | ||||
| 14 | |||||
| 15 | Ima::DBI - Database connection caching and organization | ||||
| 16 | |||||
| 17 | =head1 SYNOPSIS | ||||
| 18 | |||||
| 19 | package Foo; | ||||
| 20 | use base 'Ima::DBI'; | ||||
| 21 | |||||
| 22 | # Class-wide methods. | ||||
| 23 | Foo->set_db($db_name, $data_source, $user, $password); | ||||
| 24 | Foo->set_db($db_name, $data_source, $user, $password, \%attr); | ||||
| 25 | |||||
| 26 | my @database_names = Foo->db_names; | ||||
| 27 | my @database_handles = Foo->db_handles; | ||||
| 28 | |||||
| 29 | Foo->set_sql($sql_name, $statement, $db_name); | ||||
| 30 | Foo->set_sql($sql_name, $statement, $db_name, $cache); | ||||
| 31 | |||||
| 32 | my @statement_names = Foo->sql_names; | ||||
| 33 | |||||
| 34 | # Object methods. | ||||
| 35 | $dbh = $obj->db_*; # Where * is the name of the db connection. | ||||
| 36 | $sth = $obj->sql_*; # Where * is the name of the sql statement. | ||||
| 37 | $sth = $obj->sql_*(@sql_pieces); | ||||
| 38 | |||||
| 39 | $obj->DBIwarn($what, $doing); | ||||
| 40 | |||||
| 41 | my $rc = $obj->commit; | ||||
| 42 | my $rc = $obj->commit(@db_names); | ||||
| 43 | |||||
| 44 | my $rc = $obj->rollback; | ||||
| 45 | my $rc = $obj->rollback(@db_names); | ||||
| 46 | |||||
| 47 | |||||
| 48 | =head1 DESCRIPTION | ||||
| 49 | |||||
| 50 | Ima::DBI attempts to organize and facilitate caching and more efficient | ||||
| 51 | use of database connections and statement handles by storing DBI and | ||||
| 52 | SQL information with your class (instead of as seperate objects). | ||||
| 53 | This allows you to pass around just one object without worrying about | ||||
| 54 | a trail of DBI handles behind it. | ||||
| 55 | |||||
| 56 | One of the things I always found annoying about writing large programs | ||||
| 57 | with DBI was making sure that I didn't have duplicate database handles | ||||
| 58 | open. I was also annoyed by the somewhat wasteful nature of the | ||||
| 59 | prepare/execute/finish route I'd tend to go through in my subroutines. | ||||
| 60 | The new DBI->connect_cached and DBI->prepare_cached helped a lot, but | ||||
| 61 | I still had to throw around global datasource, username and password | ||||
| 62 | information. | ||||
| 63 | |||||
| 64 | So, after a while I grew a small library of DBI helper routines and | ||||
| 65 | techniques. Ima::DBI is the culmination of all this, put into a nice(?), | ||||
| 66 | clean(?) class to be inherited from. | ||||
| 67 | |||||
| 68 | =head2 Why should I use this thing? | ||||
| 69 | |||||
| 70 | Ima::DBI is a little odd, and it's kinda hard to explain. So lemme | ||||
| 71 | explain why you'd want to use this thing... | ||||
| 72 | |||||
| 73 | =over 4 | ||||
| 74 | |||||
| 75 | =item * Consolidation of all SQL statements and database information | ||||
| 76 | |||||
| 77 | No matter what, embedding one language into another is messy. | ||||
| 78 | DBI alleviates this somewhat, but I've found a tendency to have that | ||||
| 79 | scatter the SQL around inside the Perl code. Ima::DBI allows you to | ||||
| 80 | easily group the SQL statements in one place where they are easier to | ||||
| 81 | maintain (especially if one developer is writing the SQL, another writing | ||||
| 82 | the Perl). Alternatively, you can place your SQL statement alongside | ||||
| 83 | the code which uses it. Whatever floats your boat. | ||||
| 84 | |||||
| 85 | Database connection information (data source, username, password, | ||||
| 86 | atrributes, etc...) can also be consolidated together and tracked. | ||||
| 87 | |||||
| 88 | Both the SQL and the connection info are probably going to change a lot, | ||||
| 89 | so having them well organized and easy to find in the code is a Big Help. | ||||
| 90 | |||||
| 91 | =item * Holds off opening a database connection until necessary. | ||||
| 92 | |||||
| 93 | While Ima::DBI is informed of all your database connections and SQL | ||||
| 94 | statements at compile-time, it will not connect to the database until | ||||
| 95 | you actually prepare a statement on that connection. | ||||
| 96 | |||||
| 97 | This is obviously very good for programs that sometimes never touch | ||||
| 98 | the database. It's also good for code that has lots of possible | ||||
| 99 | connections and statements, but which typically only use a few. | ||||
| 100 | Kinda like an autoloader. | ||||
| 101 | |||||
| 102 | =item * Easy integration of the DBI handles into your class | ||||
| 103 | |||||
| 104 | Ima::DBI causes each database handle to be associated with your class, | ||||
| 105 | allowing you to pull handles from an instance of your object, as well | ||||
| 106 | as making many oft-used DBI methods available directly from your | ||||
| 107 | instance. | ||||
| 108 | |||||
| 109 | This gives you a cleaner OO design, since you can now just throw | ||||
| 110 | around the object as usual and it will carry its associated DBI | ||||
| 111 | baggage with it. | ||||
| 112 | |||||
| 113 | =item * Honors taint mode | ||||
| 114 | |||||
| 115 | It always struck me as a design deficiency that tainted SQL statements | ||||
| 116 | could be passed to $sth->prepare(). For example: | ||||
| 117 | |||||
| 118 | # $user is from an untrusted source and is tainted. | ||||
| 119 | $user = get_user_data_from_the_outside_world; | ||||
| 120 | $sth = $dbh->prepare('DELETE FROM Users WHERE User = $user'); | ||||
| 121 | |||||
| 122 | Looks innocent enough... but what if $user was the string "1 OR User LIKE | ||||
| 123 | '%'". You just blew away all your users. Hope you have backups. | ||||
| 124 | |||||
| 125 | Ima::DBI turns on the DBI->connect Taint attribute so that all DBI | ||||
| 126 | methods (except execute()) will no longer accept tainted data. | ||||
| 127 | See L<DBI/Taint> for details. | ||||
| 128 | |||||
| 129 | =item * Taints returned data | ||||
| 130 | |||||
| 131 | Databases should be like any other system call. It's the scary Outside | ||||
| 132 | World, thus it should be tainted. Simple. Ima::DBI turns on DBI's Taint | ||||
| 133 | attribute on each connection. This feature is overridable by passing | ||||
| 134 | your own Taint attribute to set_db as normal for DBI. See L<DBI/Taint> | ||||
| 135 | for details. | ||||
| 136 | |||||
| 137 | =item * Encapsulation of some of the more repetitive bits of everyday DBI usage | ||||
| 138 | |||||
| 139 | I get lazy a lot and I forget to do things I really should, like using | ||||
| 140 | bind_cols(), or rigorous error checking. Ima::DBI does some of this | ||||
| 141 | stuff automatically, other times it just makes it more convenient. | ||||
| 142 | |||||
| 143 | =item * Encapsulation of DBI's cache system | ||||
| 144 | |||||
| 145 | DBI's automatic handle caching system is relatively new, and some people | ||||
| 146 | aren't aware of its use. Ima::DBI uses it automatically, so you don't | ||||
| 147 | have to worry about it. (It even makes it a bit more efficient) | ||||
| 148 | |||||
| 149 | =item * Sharing of database and sql information amongst inherited classes | ||||
| 150 | |||||
| 151 | Any SQL statements and connections created by a class are available to | ||||
| 152 | its children via normal method inheritance. | ||||
| 153 | |||||
| 154 | =item * Guarantees one connection per program. | ||||
| 155 | |||||
| 156 | One program, one database connection (per database user). One program, | ||||
| 157 | one prepared statement handle (per statement, per database user). | ||||
| 158 | That's what Ima::DBI enforces. Extremely handy in persistant environments | ||||
| 159 | (servers, daemons, mod_perl, FastCGI, etc...) | ||||
| 160 | |||||
| 161 | =item * Encourages use of bind parameters and columns | ||||
| 162 | |||||
| 163 | Bind parameters are safer and more efficient than embedding the column | ||||
| 164 | information straight into the SQL statement. Bind columns are more | ||||
| 165 | efficient than normal fetching. Ima::DBI pretty much requires the usage | ||||
| 166 | of the former, and eases the use of the latter. | ||||
| 167 | |||||
| 168 | =back | ||||
| 169 | |||||
| 170 | =head2 Why shouldn't I use this thing. | ||||
| 171 | |||||
| 172 | =over 4 | ||||
| 173 | |||||
| 174 | =item * It's all about OO | ||||
| 175 | |||||
| 176 | Although it is possible to use Ima::DBI as a stand-alone module as | ||||
| 177 | part of a function-oriented design, its generally not to be used | ||||
| 178 | unless integrated into an object-oriented design. | ||||
| 179 | |||||
| 180 | =item * Overkill for small programs | ||||
| 181 | |||||
| 182 | =item * Overkill for programs with only one or two SQL statements | ||||
| 183 | |||||
| 184 | Its up to you whether the trouble of setting up a class and jumping | ||||
| 185 | through the necessary Ima::DBI hoops is worth it for small programs. | ||||
| 186 | To me, it takes just as much time to set up an Ima::DBI subclass as it | ||||
| 187 | would to access DBI without it... but then again I wrote the module. | ||||
| 188 | YMMV. | ||||
| 189 | |||||
| 190 | =item * Overkill for programs that only use their SQL statements once | ||||
| 191 | |||||
| 192 | Ima::DBI's caching might prove to be an unecessary performance hog if | ||||
| 193 | you never use the same SQL statement twice. Not sure, I haven't | ||||
| 194 | looked into it. | ||||
| 195 | |||||
| 196 | =back | ||||
| 197 | |||||
| 198 | |||||
| 199 | =head1 USAGE | ||||
| 200 | |||||
| 201 | The basic steps to "DBIing" a class are: | ||||
| 202 | |||||
| 203 | =over 4 | ||||
| 204 | |||||
| 205 | =item 1 | ||||
| 206 | |||||
| 207 | Inherit from Ima::DBI | ||||
| 208 | |||||
| 209 | =item 2 | ||||
| 210 | |||||
| 211 | Set up and name all your database connections via set_db() | ||||
| 212 | |||||
| 213 | =item 3 | ||||
| 214 | |||||
| 215 | Set up and name all your SQL statements via set_sql() | ||||
| 216 | |||||
| 217 | =item 4 | ||||
| 218 | |||||
| 219 | Use sql_* to retrieve your statement handles ($sth) as needed and db_* | ||||
| 220 | to retreive database handles ($dbh). | ||||
| 221 | |||||
| 222 | |||||
| 223 | =back | ||||
| 224 | |||||
| 225 | Have a look at L<EXAMPLE> below. | ||||
| 226 | |||||
| 227 | =head1 TAINTING | ||||
| 228 | |||||
| 229 | Ima::DBI, by default, uses DBI's Taint flag on all connections. | ||||
| 230 | |||||
| 231 | This means that Ima::DBI methods do not accept tainted data, and that all | ||||
| 232 | data fetched from the database will be tainted. This may be different | ||||
| 233 | from the DBI behavior you're used to. See L<DBI/Taint> for details. | ||||
| 234 | |||||
| 235 | =head1 Class Methods | ||||
| 236 | |||||
| 237 | =head2 set_db | ||||
| 238 | |||||
| 239 | Foo->set_db($db_name, $data_source, $user, $password); | ||||
| 240 | Foo->set_db($db_name, $data_source, $user, $password, \%attr); | ||||
| 241 | |||||
| 242 | This method is used in place of DBI->connect to create your database | ||||
| 243 | handles. It sets up a new DBI database handle associated to $db_name. | ||||
| 244 | All other arguments are passed through to DBI->connect_cached. | ||||
| 245 | |||||
| 246 | A new method is created for each db you setup. This new method is called | ||||
| 247 | "db_$db_name"... so, for example, Foo->set_db("foo", ...) will create | ||||
| 248 | a method called "db_foo()". (Spaces in $db_name will be translated into | ||||
| 249 | underscores: '_') | ||||
| 250 | |||||
| 251 | %attr is combined with a set of defaults (RaiseError => 1, AutoCommit | ||||
| 252 | => 0, PrintError => 0, Taint => 1). This is a better default IMHO, | ||||
| 253 | however it does give databases without transactions (such as MySQL) a | ||||
| 254 | hard time. Be sure to turn AutoCommit back on if your database does | ||||
| 255 | not support transactions. | ||||
| 256 | |||||
| 257 | The actual database handle creation (and thus the database connection) | ||||
| 258 | is held off until a prepare is attempted with this handle. | ||||
| 259 | |||||
| 260 | =cut | ||||
| 261 | |||||
| 262 | sub _croak { my $self = shift; require Carp; Carp::croak(@_) } | ||||
| 263 | |||||
| 264 | # spent 726µs (229+497) within Ima::DBI::set_db which was called
# once (229µs+497µs) by Class::DBI::set_db at line 212 of Class/DBI.pm | ||||
| 265 | 1 | 6µs | my $class = shift; | ||
| 266 | 1 | 6µs | my $db_name = shift or $class->_croak("Need a db name"); | ||
| 267 | 1 | 26µs | 1 | 8µs | $db_name =~ s/\s/_/g; # spent 8µs making 1 call to Ima::DBI::CORE:subst |
| 268 | |||||
| 269 | 1 | 6µs | my $data_source = shift or $class->_croak("Need a data source"); | ||
| 270 | 1 | 5µs | my $user = shift || ""; | ||
| 271 | 1 | 6µs | my $password = shift || ""; | ||
| 272 | 1 | 6µs | my $attr = shift || {}; | ||
| 273 | 1 | 7µs | ref $attr eq 'HASH' or $class->_croak("$attr must be a hash reference"); | ||
| 274 | 1 | 48µs | 1 | 197µs | $attr = $class->_add_default_attributes($attr); # spent 197µs making 1 call to Ima::DBI::_add_default_attributes |
| 275 | |||||
| 276 | 1 | 44µs | 1 | 255µs | $class->_remember_handle($db_name); # spent 255µs making 1 call to Ima::DBI::_remember_handle |
| 277 | 3 | 739µs | 1 | 102µs | no strict 'refs'; # spent 102µs making 1 call to strict::unimport |
| 278 | 1 | 49µs | 1 | 37µs | *{ $class . "::db_$db_name" } = # spent 37µs making 1 call to Ima::DBI::_mk_db_closure |
| 279 | $class->_mk_db_closure($data_source, $user, $password, $attr); | ||||
| 280 | |||||
| 281 | 1 | 17µs | return 1; | ||
| 282 | } | ||||
| 283 | |||||
| 284 | # spent 197µs (77+120) within Ima::DBI::_add_default_attributes which was called
# once (77µs+120µs) by Ima::DBI::set_db at line 274 | ||||
| 285 | 1 | 6µs | my ($class, $user_attr) = @_; | ||
| 286 | 1 | 39µs | 1 | 120µs | my %attr = $class->_default_attributes; # spent 120µs making 1 call to Class::DBI::_default_attributes |
| 287 | 1 | 12µs | @attr{ keys %$user_attr } = values %$user_attr; | ||
| 288 | 1 | 21µs | return \%attr; | ||
| 289 | } | ||||
| 290 | |||||
| 291 | # spent 16µs within Ima::DBI::_default_attributes which was called
# once (16µs+0s) by Class::DBI::_default_attributes at line 201 of Class/DBI.pm | ||||
| 292 | ( | ||||
| 293 | 1 | 24µs | RaiseError => 1, | ||
| 294 | AutoCommit => 0, | ||||
| 295 | PrintError => 0, | ||||
| 296 | Taint => 1, | ||||
| 297 | RootClass => "DBIx::ContextualFetch" | ||||
| 298 | ); | ||||
| 299 | } | ||||
| 300 | |||||
| 301 | # spent 255µs (86+169) within Ima::DBI::_remember_handle which was called
# once (86µs+169µs) by Ima::DBI::set_db at line 276 | ||||
| 302 | 1 | 6µs | my ($class, $db) = @_; | ||
| 303 | 1 | 41µs | 1 | 27µs | my $handles = $class->__Database_Names || []; # spent 27µs making 1 call to Class::Data::Inheritable::__ANON__[Class/Data/Inheritable.pm:23] |
| 304 | 1 | 5µs | push @$handles, $db; | ||
| 305 | 1 | 26µs | 1 | 142µs | $class->__Database_Names($handles); # spent 142µs making 1 call to Class::Data::Inheritable::__ANON__[Class/Data/Inheritable.pm:23] |
| 306 | } | ||||
| 307 | |||||
| 308 | # spent 37µs within Ima::DBI::_mk_db_closure which was called
# once (37µs+0s) by Ima::DBI::set_db at line 278 | ||||
| 309 | 1 | 12µs | my ($class, @connection) = @_; | ||
| 310 | 1 | 4µs | my $dbh; | ||
| 311 | # spent 170ms (392µs+169) within Ima::DBI::__ANON__[/project/perl/lib/Ima/DBI.pm:316] which was called 8 times, avg 21.2ms/call:
# 4 times (179µs+30.4ms) by Class::DBI::Pg::pg_version at line 90 of Class/DBI/Pg.pm, avg 7.64ms/call
# 2 times (103µs+138ms) by Class::DBI::Pg::set_up_table at line 12 of Class/DBI/Pg.pm, avg 69.2ms/call
# 2 times (110µs+734µs) by Ima::DBI::__ANON__[/project/perl/lib/Ima/DBI.pm:384] at line 376, avg 422µs/call | ||||
| 312 | 8 | 529µs | 15 | 169ms | unless ($dbh && $dbh->FETCH('Active') && $dbh->ping) { # spent 138ms making 1 call to DBI::connect_cached
# spent 31.4ms making 7 calls to DBI::db::ping, avg 4.49ms/call
# spent 112µs making 7 calls to DBI::common::FETCH, avg 16µs/call |
| 313 | $dbh = DBI->connect_cached(@connection); | ||||
| 314 | } | ||||
| 315 | 8 | 127µs | return $dbh; | ||
| 316 | 1 | 26µs | }; | ||
| 317 | } | ||||
| 318 | |||||
| 319 | =head2 set_sql | ||||
| 320 | |||||
| 321 | Foo->set_sql($sql_name, $statement, $db_name); | ||||
| 322 | Foo->set_sql($sql_name, $statement, $db_name, $cache); | ||||
| 323 | |||||
| 324 | This method is used in place of DBI->prepare to create your statement | ||||
| 325 | handles. It sets up a new statement handle associated to $sql_name using | ||||
| 326 | the database connection associated with $db_name. $statement is passed | ||||
| 327 | through to either DBI->prepare or DBI->prepare_cached (depending on | ||||
| 328 | $cache) to create the statement handle. | ||||
| 329 | |||||
| 330 | If $cache is true or isn't given, then prepare_cached() will be used to | ||||
| 331 | prepare the statement handle and it will be cached. If $cache is false | ||||
| 332 | then a normal prepare() will be used and the statement handle will be | ||||
| 333 | recompiled on every sql_*() call. If you have a statement which changes | ||||
| 334 | a lot or is used very infrequently you might not want it cached. | ||||
| 335 | |||||
| 336 | A new method is created for each statement you set up. This new method | ||||
| 337 | is "sql_$sql_name"... so, as with set_db(), Foo->set_sql("bar", ..., | ||||
| 338 | "foo"); will create a method called "sql_bar()" which uses the database | ||||
| 339 | connection from "db_foo()". Again, spaces in $sql_name will be translated | ||||
| 340 | into underscores ('_'). | ||||
| 341 | |||||
| 342 | The actual statement handle creation is held off until sql_* is first | ||||
| 343 | called on this name. | ||||
| 344 | |||||
| 345 | =cut | ||||
| 346 | |||||
| 347 | # spent 3.67ms (2.04+1.63) within Ima::DBI::set_sql which was called 13 times, avg 283µs/call:
# 13 times (2.04ms+1.63ms) by Class::DBI::set_sql at line 933 of Class/DBI.pm, avg 283µs/call | ||||
| 348 | 13 | 81µs | my ($class, $sql_name, $statement, $db_name, $cache) = @_; | ||
| 349 | 13 | 87µs | $cache = 1 unless defined $cache; | ||
| 350 | |||||
| 351 | # ------------------------- sql_* closure ----------------------- # | ||||
| 352 | 13 | 61µs | my $db_meth = $db_name; | ||
| 353 | 13 | 311µs | 13 | 112µs | $db_meth =~ s/\s/_/g; # spent 112µs making 13 calls to Ima::DBI::CORE:subst, avg 9µs/call |
| 354 | 13 | 83µs | $db_meth = "db_$db_meth"; | ||
| 355 | |||||
| 356 | 13 | 216µs | 13 | 60µs | (my $sql_meth = $sql_name) =~ s/\s/_/g; # spent 60µs making 13 calls to Ima::DBI::CORE:subst, avg 5µs/call |
| 357 | 13 | 73µs | $sql_meth = "sql_$sql_meth"; | ||
| 358 | |||||
| 359 | # Remember the name of this handle for the class. | ||||
| 360 | 13 | 269µs | 13 | 369µs | my $handles = $class->__Statement_Names || []; # spent 369µs making 13 calls to Class::Data::Inheritable::__ANON__[Class/Data/Inheritable.pm:23], avg 28µs/call |
| 361 | 13 | 77µs | push @$handles, $sql_name; | ||
| 362 | 13 | 202µs | 13 | 710µs | $class->__Statement_Names($handles); # spent 710µs making 13 calls to Class::Data::Inheritable::__ANON__[Class/Data/Inheritable.pm:23], avg 55µs/call |
| 363 | |||||
| 364 | 3 | 994µs | 1 | 96µs | no strict 'refs'; # spent 96µs making 1 call to strict::unimport |
| 365 | 13 | 497µs | 13 | 380µs | *{ $class . "::$sql_meth" } = # spent 380µs making 13 calls to Ima::DBI::_mk_sql_closure, avg 29µs/call |
| 366 | $class->_mk_sql_closure($sql_name, $statement, $db_meth, $cache); | ||||
| 367 | |||||
| 368 | 13 | 187µs | return 1; | ||
| 369 | } | ||||
| 370 | |||||
| 371 | # spent 380µs within Ima::DBI::_mk_sql_closure which was called 13 times, avg 29µs/call:
# 13 times (380µs+0s) by Ima::DBI::set_sql at line 365, avg 29µs/call | ||||
| 372 | 13 | 96µs | my ($class, $sql_name, $statement, $db_meth, $cache) = @_; | ||
| 373 | |||||
| 374 | # spent 6.79ms (245µs+6.55) within Ima::DBI::__ANON__[/project/perl/lib/Ima/DBI.pm:384] which was called 2 times, avg 3.40ms/call:
# once (145µs+4.54ms) by Class::DBI::Plugin::RetrieveAll::__ANON__[/project/perl/lib/Class/DBI/Plugin/RetrieveAll.pm:77] at line 76 of Class/DBI/Plugin/RetrieveAll.pm
# once (100µs+2.01ms) by Class::DBI::_flesh at line 857 of Class/DBI.pm | ||||
| 375 | 2 | 12µs | my $class = shift; | ||
| 376 | 2 | 40µs | 2 | 844µs | my $dbh = $class->$db_meth(); # spent 844µs making 2 calls to Ima::DBI::__ANON__[Ima/DBI.pm:316], avg 422µs/call |
| 377 | |||||
| 378 | # Everything must pass through sprintf, even if @_ is empty. | ||||
| 379 | # This is to do proper '%%' translation. | ||||
| 380 | 2 | 100µs | 2 | 4.75ms | my $sql = $class->transform_sql($statement => @_); # spent 4.75ms making 2 calls to Class::DBI::transform_sql, avg 2.37ms/call |
| 381 | 2 | 225µs | 2 | 957µs | return $cache # spent 957µs making 2 calls to DBI::db::prepare_cached, avg 479µs/call |
| 382 | ? $dbh->prepare_cached($sql) | ||||
| 383 | : $dbh->prepare($sql); | ||||
| 384 | 13 | 322µs | }; | ||
| 385 | } | ||||
| 386 | |||||
| 387 | =head2 transform_sql | ||||
| 388 | |||||
| 389 | To make up for the limitations of bind parameters, $statement can contain | ||||
| 390 | sprintf() style formatting (ie. %s and such) to allow dynamically | ||||
| 391 | generated SQL statements (so to get a real percent sign, use '%%'). | ||||
| 392 | |||||
| 393 | The translation of the SQL happens in transform_sql(), which can be | ||||
| 394 | overridden to do more complex transformations. See L<Class::DBI> for an | ||||
| 395 | example. | ||||
| 396 | |||||
| 397 | =cut | ||||
| 398 | |||||
| 399 | # spent 51µs within Ima::DBI::transform_sql which was called 2 times, avg 26µs/call:
# 2 times (51µs+0s) by Class::DBI::transform_sql at line 154 of Class/DBI.pm, avg 26µs/call | ||||
| 400 | 2 | 17µs | my ($class, $sql, @args) = @_; | ||
| 401 | 2 | 43µs | return sprintf $sql, @args; | ||
| 402 | } | ||||
| 403 | |||||
| 404 | =head2 db_names / db_handles | ||||
| 405 | |||||
| 406 | my @database_names = Foo->db_names; | ||||
| 407 | my @database_handles = Foo->db_handles; | ||||
| 408 | my @database_handles = Foo->db_handles(@db_names); | ||||
| 409 | |||||
| 410 | Returns a list of the database handles set up for this class using | ||||
| 411 | set_db(). This includes all inherited handles. | ||||
| 412 | |||||
| 413 | db_names() simply returns the name of the handle, from which it is | ||||
| 414 | possible to access it by converting it to a method name and calling | ||||
| 415 | that db method... | ||||
| 416 | |||||
| 417 | my @db_names = Foo->db_names; | ||||
| 418 | my $db_meth = 'db_'.$db_names[0]; | ||||
| 419 | my $dbh = $foo->$db_meth; | ||||
| 420 | |||||
| 421 | Icky, eh? Fortunately, db_handles() does this for you and returns a | ||||
| 422 | list of database handles in the same order as db_names(). B<Use this | ||||
| 423 | sparingly> as it will connect you to the database if you weren't | ||||
| 424 | already connected. | ||||
| 425 | |||||
| 426 | If given @db_names, db_handles() will return only the handles for | ||||
| 427 | those connections. | ||||
| 428 | |||||
| 429 | These both work as either class or object methods. | ||||
| 430 | |||||
| 431 | =cut | ||||
| 432 | |||||
| 433 | sub db_names { @{ $_[0]->__Database_Names || [] } } | ||||
| 434 | |||||
| 435 | sub db_handles { | ||||
| 436 | my ($self, @db_names) = @_; | ||||
| 437 | @db_names = $self->db_names unless @db_names; | ||||
| 438 | return map $self->$_(), map "db_$_", @db_names; | ||||
| 439 | } | ||||
| 440 | |||||
| 441 | =head2 sql_names | ||||
| 442 | |||||
| 443 | my @statement_names = Foo->sql_names; | ||||
| 444 | |||||
| 445 | Similar to db_names() this returns the names of all SQL statements set | ||||
| 446 | up for this class using set_sql(), inherited or otherwise. | ||||
| 447 | |||||
| 448 | There is no corresponding sql_handles() because we can't know what | ||||
| 449 | arguments to pass in. | ||||
| 450 | |||||
| 451 | =cut | ||||
| 452 | |||||
| 453 | sub sql_names { @{ $_[0]->__Statement_Names || [] } } | ||||
| 454 | |||||
| 455 | =head1 Object Methods | ||||
| 456 | |||||
| 457 | =head2 db_* | ||||
| 458 | |||||
| 459 | $dbh = $obj->db_*; | ||||
| 460 | |||||
| 461 | This is how you directly access a database handle you set up with set_db. | ||||
| 462 | |||||
| 463 | The actual particular method name is derived from what you told set_db. | ||||
| 464 | |||||
| 465 | db_* will handle all the issues of making sure you're already | ||||
| 466 | connected to the database. | ||||
| 467 | |||||
| 468 | =head2 sql_* | ||||
| 469 | |||||
| 470 | $sth = $obj->sql_*; | ||||
| 471 | $sth = $obj->sql_*(@sql_pieces); | ||||
| 472 | |||||
| 473 | sql_*() is a catch-all name for the methods you set up with set_sql(). | ||||
| 474 | For instance, if you did: | ||||
| 475 | |||||
| 476 | Foo->set_sql('GetAllFoo', 'Select * From Foo', 'SomeDb'); | ||||
| 477 | |||||
| 478 | you'd run that statement with sql_GetAllFoo(). | ||||
| 479 | |||||
| 480 | sql_* will handle all the issues of making sure the database is | ||||
| 481 | already connected, and the statement handle is prepared. It returns a | ||||
| 482 | prepared statement handle for you to use. (You're expected to | ||||
| 483 | execute() it) | ||||
| 484 | |||||
| 485 | If sql_*() is given a list of @sql_pieces it will use them to fill in | ||||
| 486 | your statement, assuming you have sprintf() formatting tags in your | ||||
| 487 | statement. For example: | ||||
| 488 | |||||
| 489 | Foo->set_sql('GetTable', 'Select * From %s', 'Things'); | ||||
| 490 | |||||
| 491 | # Assuming we have created an object... this will prepare the | ||||
| 492 | # statement 'Select * From Bar' | ||||
| 493 | $sth = $obj->sql_Search('Bar'); | ||||
| 494 | |||||
| 495 | Be B<very careful> with what you feed this function. It cannot | ||||
| 496 | do any quoting or escaping for you, so it is totally up to you | ||||
| 497 | to take care of that. Fortunately if you have tainting on you | ||||
| 498 | will be spared the worst. | ||||
| 499 | |||||
| 500 | It is recommended you only use this in cases where bind parameters | ||||
| 501 | will not work. | ||||
| 502 | |||||
| 503 | =head2 DBIwarn | ||||
| 504 | |||||
| 505 | $obj->DBIwarn($what, $doing); | ||||
| 506 | |||||
| 507 | Produces a useful error for exceptions with DBI. | ||||
| 508 | |||||
| 509 | B<I'm not particularly happy with this interface> | ||||
| 510 | |||||
| 511 | Most useful like this: | ||||
| 512 | |||||
| 513 | eval { | ||||
| 514 | $self->sql_Something->execute($self->{ID}, @stuff); | ||||
| 515 | }; | ||||
| 516 | if($@) { | ||||
| 517 | $self->DBIwarn($self->{ID}, 'Something'); | ||||
| 518 | return; | ||||
| 519 | } | ||||
| 520 | |||||
| 521 | |||||
| 522 | =cut | ||||
| 523 | |||||
| 524 | sub DBIwarn { | ||||
| 525 | my ($self, $thing, $doing) = @_; | ||||
| 526 | my $errstr = "Failure while doing '$doing' with '$thing'\n"; | ||||
| 527 | $errstr .= $@ if $@; | ||||
| 528 | |||||
| 529 | require Carp; | ||||
| 530 | Carp::carp $errstr; | ||||
| 531 | |||||
| 532 | return 1; | ||||
| 533 | } | ||||
| 534 | |||||
| 535 | =head1 Modified database handle methods | ||||
| 536 | |||||
| 537 | Ima::DBI makes some of the methods available to your object that are | ||||
| 538 | normally only available via the database handle. In addition, it | ||||
| 539 | spices up the API a bit. | ||||
| 540 | |||||
| 541 | =head2 commit | ||||
| 542 | |||||
| 543 | $rc = $obj->commit; | ||||
| 544 | $rc = $obj->commit(@db_names); | ||||
| 545 | |||||
| 546 | Derived from $dbh->commit() and basically does the same thing. | ||||
| 547 | |||||
| 548 | If called with no arguments, it causes commit() to be called on all | ||||
| 549 | database handles associated with $obj. Otherwise it commits all | ||||
| 550 | database handles whose names are listed in @db_names. | ||||
| 551 | |||||
| 552 | Alternatively, you may like to do: $rc = $obj->db_Name->commit; | ||||
| 553 | |||||
| 554 | If all the commits succeeded it returns true, false otherwise. | ||||
| 555 | |||||
| 556 | =cut | ||||
| 557 | |||||
| 558 | sub commit { | ||||
| 559 | my ($self, @db_names) = @_; | ||||
| 560 | return grep(!$_, map $_->commit, $self->db_handles(@db_names)) ? 0 : 1; | ||||
| 561 | } | ||||
| 562 | |||||
| 563 | =head2 rollback | ||||
| 564 | |||||
| 565 | $rc = $obj->rollback; | ||||
| 566 | $rc = $obj->rollback(@db_names); | ||||
| 567 | |||||
| 568 | Derived from $dbh->rollback, this acts just like Ima::DBI->commit, | ||||
| 569 | except that it calls rollback(). | ||||
| 570 | |||||
| 571 | Alternatively, you may like to do: $rc = $obj->db_Name->rollback; | ||||
| 572 | |||||
| 573 | If all the rollbacks succeeded it returns true, false otherwise. | ||||
| 574 | |||||
| 575 | =cut | ||||
| 576 | |||||
| 577 | sub rollback { | ||||
| 578 | my ($self, @db_names) = @_; | ||||
| 579 | return grep(!$_, map $_->rollback, $self->db_handles(@db_names)) ? 0 : 1; | ||||
| 580 | } | ||||
| 581 | |||||
| 582 | =head1 EXAMPLE | ||||
| 583 | |||||
| 584 | package Foo; | ||||
| 585 | use base qw(Ima::DBI); | ||||
| 586 | |||||
| 587 | # Set up database connections (but don't connect yet) | ||||
| 588 | Foo->set_db('Users', 'dbi:Oracle:Foo', 'admin', 'passwd'); | ||||
| 589 | Foo->set_db('Customers', 'dbi:Oracle:Foo', 'Staff', 'passwd'); | ||||
| 590 | |||||
| 591 | # Set up SQL statements to be used through out the program. | ||||
| 592 | Foo->set_sql('FindUser', <<"SQL", 'Users'); | ||||
| 593 | SELECT * | ||||
| 594 | FROM Users | ||||
| 595 | WHERE Name LIKE ? | ||||
| 596 | SQL | ||||
| 597 | |||||
| 598 | Foo->set_sql('ChangeLanguage', <<"SQL", 'Customers'); | ||||
| 599 | UPDATE Customers | ||||
| 600 | SET Language = ? | ||||
| 601 | WHERE Country = ? | ||||
| 602 | SQL | ||||
| 603 | |||||
| 604 | # rest of the class as usual. | ||||
| 605 | |||||
| 606 | package main; | ||||
| 607 | |||||
| 608 | $obj = Foo->new; | ||||
| 609 | |||||
| 610 | eval { | ||||
| 611 | # Does connect & prepare | ||||
| 612 | my $sth = $obj->sql_FindUser; | ||||
| 613 | # bind_params, execute & bind_columns | ||||
| 614 | $sth->execute(['Likmi%'], [\($name)]); | ||||
| 615 | while( $sth->fetch ) { | ||||
| 616 | print $name; | ||||
| 617 | } | ||||
| 618 | |||||
| 619 | # Uses cached database and statement handles | ||||
| 620 | $sth = $obj->sql_FindUser; | ||||
| 621 | # bind_params & execute. | ||||
| 622 | $sth->execute('%Hock'); | ||||
| 623 | @names = $sth->fetchall; | ||||
| 624 | |||||
| 625 | # connects, prepares | ||||
| 626 | $rows_altered = $obj->sql_ChangeLanguage->execute(qw(es_MX mx)); | ||||
| 627 | }; | ||||
| 628 | unless ($@) { | ||||
| 629 | # Everything went okay, commit the changes to the customers. | ||||
| 630 | $obj->commit('Customers'); | ||||
| 631 | } | ||||
| 632 | else { | ||||
| 633 | $obj->rollback('Customers'); | ||||
| 634 | warn "DBI failure: $@"; | ||||
| 635 | } | ||||
| 636 | |||||
| 637 | |||||
| 638 | =head1 TODO, Caveat, BUGS, etc.... | ||||
| 639 | |||||
| 640 | =over 4 | ||||
| 641 | |||||
| 642 | =item I seriously doubt that it's thread safe. | ||||
| 643 | |||||
| 644 | You can bet cupcackes to sno-cones that much havoc will be wrought if | ||||
| 645 | Ima::DBI is used in a threaded Perl. | ||||
| 646 | |||||
| 647 | =item Should make use of private_* handle method to store information | ||||
| 648 | |||||
| 649 | =item The docs stink. | ||||
| 650 | |||||
| 651 | The docs were originally written when I didn't have a good handle on | ||||
| 652 | the module and how it will be used in practical cases. I need to | ||||
| 653 | rewrite the docs from the ground up. | ||||
| 654 | |||||
| 655 | =item Need to add debugging hooks. | ||||
| 656 | |||||
| 657 | The thing which immediately comes to mind is a Verbose flag to print | ||||
| 658 | out SQL statements as they are made as well as mention when database | ||||
| 659 | connections are made, etc... | ||||
| 660 | |||||
| 661 | =back | ||||
| 662 | |||||
| 663 | =head1 MAINTAINER | ||||
| 664 | |||||
| 665 | Tony Bowden <tony@tmtm.com> | ||||
| 666 | |||||
| 667 | =head1 ORIGINAL AUTHOR | ||||
| 668 | |||||
| 669 | Michael G Schwern <schwern@pobox.com> | ||||
| 670 | |||||
| 671 | =head1 LICENSE | ||||
| 672 | |||||
| 673 | This module is free software. You may distribute under the same terms | ||||
| 674 | as Perl itself. IT COMES WITHOUT WARRANTY OF ANY KIND. | ||||
| 675 | |||||
| 676 | =head1 THANKS MUCHLY | ||||
| 677 | |||||
| 678 | Tim Bunce, for enduring many DBI questions and adding Taint, | ||||
| 679 | prepare_cached and connect_cached methods to DBI, simplifying this | ||||
| 680 | greatly! | ||||
| 681 | |||||
| 682 | Arena Networks, for effectively paying for Mike to write most of this | ||||
| 683 | module. | ||||
| 684 | |||||
| 685 | =head1 SEE ALSO | ||||
| 686 | |||||
| 687 | L<DBI>. | ||||
| 688 | |||||
| 689 | You may also choose to check out L<Class::DBI> which hides most of this | ||||
| 690 | from view. | ||||
| 691 | |||||
| 692 | =cut | ||||
| 693 | |||||
| 694 | 1 | 16µs | return 1001001; | ||
# spent 180µs within Ima::DBI::CORE:subst which was called 27 times, avg 7µs/call:
# 13 times (112µs+0s) by Ima::DBI::set_sql at line 353 of Ima/DBI.pm, avg 9µs/call
# 13 times (60µs+0s) by Ima::DBI::set_sql at line 356 of Ima/DBI.pm, avg 5µs/call
# once (8µs+0s) by Ima::DBI::set_db at line 267 of Ima/DBI.pm |