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 )