Detecting and Examining Databases 101
Arthur Axel fREW Schmidt
YAPC::NA
Orlando, Florida
2014 June 23, 16:00
(blah blah hiring blah)
Me
What's the problem?
What's the problem?
- sometimes you need to generate different SQL
per DB
- sometimes you need to just treat $dbh's differently
Why not $dbh->{Driver}->{Name}
Why not $dbh->{Driver}->{Name}
- Driver != Database
- important (to me) example: ODBC
People do try this, way too often
People do try this, way too often
What works?
What works?
- Nested "re"detection
- DBIC does this...but it's
- incomprehensible
- not extensible
- not reusable
- almost completely hardcoded
Solution: DBIx::Introspector
Solution: DBIx::Introspector
- Faithful reimplementation of the DBIC algorithm
- Complete initial configuration fits in 50LoC
- Can add to or modify that configuration for just
yourself
DBII in action
Details: new
Details: new
DBIx::Introspector->new(drivers => '2013-12.01')
Details: decorate_driver_(un)connected
Details: decorate_driver_(un)connected
$dbii->decorate_driver_unconnected(
Pg => 'concat_sql' => '? || ?',
)
$dbii->decorate_driver_connected(
Pg => 'rdbms_version' => sub {
my $dbh = shift;
$dbh->selectcol_arrayref('SELECT VERSION()')->[0]
},
)
Details: get
Details: get
$dbii->get($dbh, $dsn, 'concat_sql')
my $dbh;
$dbii->get(sub { $dbh }, $dsn, 'concat_sql', {
dbh_fallback_connect => sub {
$dbh = DBI->connect(...)
},
});
Links:
- Slides:
https://frioux.github.io/dbix-introspector-presentation/
- Announcement
Details: Driver
Details: Driver
- name
- parents
- connected_options
- unconnected_options
- connected_determination_strategy
- unconnected_determination_strategy
Details: Driver (DBI)
DBIx::Introspector::Driver->new({
name => 'DBI',
connected_determination_strategy => sub { $_[1]->{Driver}{Name} },
unconnected_determination_strategy => sub {
my $dsn = $_[1] || $ENV{DBI_DSN} || '';
my ($driver) = $dsn =~ /dbi:([^:]+):/i;
$driver ||= $ENV{DBI_DRIVER};
return $driver
},
})
Details: Driver (Mongo {made up example})
DBIx::Introspector::Driver->new({
name => 'Mongo',
parents => ['DBI'],
})
Details: add_driver
Details: add_driver
$dbii->add_driver({
name => 'Mongo',
parents => ['DBI'],
})
Details: replace_driver
Details: replace_driver
$dbii->replace_driver({
name => 'DBI',
connected_determination_strategy => sub {
$_[1]->{Driver}{Name}
? $_[1]->{Driver}{Name}
: $_[1]->{Driver}{MegaDrive}
},
unconnected_determination_strategy => sub {
my $dsn = $_[1] || $ENV{DBI_DSN} || '';
my ($driver) = $dsn =~ /dbi:([^:]+):/i;
$driver ||= $ENV{DBI_DRIVER};
return $driver
},
})
←
→
/
#