Dancer-Plugin-Database-Core
view release on metacpan or search on metacpan
lib/Dancer/Plugin/Database/Core.pm view on Meta::CPAN
return $return_settings;
}
# Given the settings to use, try to get a database connection
sub _get_connection {
my ($settings, $logger, $hook_exec) = @_;
if (!$settings->{dsn} && !$settings->{driver}) {
die "Can't get a database connection without settings supplied!\n"
. "Please check you've supplied settings in config as per the "
. "Dancer::Plugin::Database documentation";
}
# Assemble the DSN:
my $dsn = '';
my $driver = '';
if ($settings->{dsn}) {
$dsn = $settings->{dsn};
($driver) = $dsn =~ m{^dbi:([^:]+)}i;
} else {
$dsn = "dbi:" . $settings->{driver};
$driver = $settings->{driver};
my @extra_args;
# DBD::SQLite wants 'dbname', not 'database', so special-case this
# (DBI's documentation recommends that DBD::* modules should understand
# 'database', but older versions of DBD::SQLite didn't; let's make
# things easier for our users by handling this for them):
# (I asked in RT #61117 for DBD::SQLite to support 'database', too; this
# was included in DBD::SQLite 1.33, released Mon 20 May 2011.
# Special-casing may as well stay, rather than forcing dependency on
# DBD::SQLite 1.33.
if ($driver eq 'SQLite'
&& $settings->{database} && !$settings->{dbname}) {
$settings->{dbname} = delete $settings->{database};
}
for (qw(database dbname host port sid server)) {
if (exists $settings->{$_}) {
push @extra_args, $_ . "=" . $settings->{$_};
}
}
if (my $even_more_dsn_args = $settings->{dsn_extra}) {
foreach my $arg ( keys %$even_more_dsn_args ) {
push @extra_args, $arg . '=' . $even_more_dsn_args->{$arg};
}
}
$dsn .= ':' . join(';', @extra_args) if @extra_args;
}
# If the app is configured to use UTF-8, the user will want text from the
# database in UTF-8 to Just Work, so if we know how to make that happen, do
# so, unless they've set the auto_utf8 plugin setting to a false value.
my $app_charset = $settings->{charset} || "";
my $auto_utf8 = exists $settings->{auto_utf8} ? $settings->{auto_utf8} : 1;
if (lc $app_charset eq 'utf-8' && $auto_utf8) {
# The option to pass to the DBI->connect call depends on the driver:
my %param_for_driver = (
SQLite => 'sqlite_unicode',
mysql => 'mysql_enable_utf8',
Pg => 'pg_enable_utf8',
);
my $param = $param_for_driver{$driver};
if ($param && !$settings->{dbi_params}{$param}) {
$logger->(
debug => "Adding $param to DBI connection params"
. " to enable UTF-8 support"
);
$settings->{dbi_params}{$param} = 1;
}
}
# To support the database_error hook, use DBI's HandleError option
$settings->{dbi_params}{HandleError} = sub {
my ($error, $handle) = @_;
$hook_exec->('database_error', $error, $handle);
};
my $dbh = DBI->connect($dsn,
$settings->{username}, $settings->{password}, $settings->{dbi_params}
);
if (!$dbh) {
$logger->(error => "Database connection failed - " . $DBI::errstr);
$hook_exec->('database_connection_failed', $settings);
return undef;
} elsif (exists $settings->{on_connect_do}) {
my $to_do = ref $settings->{on_connect_do} eq 'ARRAY'
? $settings->{on_connect_do}
: [ $settings->{on_connect_do} ];
for (@$to_do) {
$dbh->do($_) or
$logger->(error => "Failed to perform on-connect command $_");
}
}
$hook_exec->('database_connected', $dbh);
# Indicate whether queries generated by quick_query() etc in
# Dancer::Plugin::Database::Core::Handle should be logged or not; this seemed a
# little dirty, but DBI's docs encourage it
# ("You can stash private data into DBI handles via $h->{private_..._*}..")
$dbh->{private_dancer_plugin_database} = {
log_queries => $settings->{log_queries} || 0,
logger => $logger,
};
# Re-bless it as a Dancer::Plugin::Database::Core::Handle object, to provide nice
# extra features (unless the config specifies a different class; if it does,
# this should be a subclass of Dancer::Plugin::Database::Core::Handle in order to
# extend the features provided by it, or a direct subclass of DBI::db (or
# even DBI::db itself) to bypass the features provided by D::P::D::Handle)
my $handle_class =
$settings->{handle_class} || 'Dancer::Plugin::Database::Core::Handle';
my $package = $handle_class;
( run in 1.697 second using v1.01-cache-2.11-cpan-39bf76dae61 )