package Explain::Plugin::Database; use Mojo::Base 'Mojolicious::Plugin'; use Date::Simple; use Carp; use DBI; __PACKAGE__->attr( dbh => undef ); has connection_args => sub { [] }; sub register { my ( $self, $app, $config ) = @_; # data source name my $dsn = $config->{ dsn }; # if DSN not set directly unless ( $dsn ) { # driver my $driver = $config->{ driver } || 'Pg'; # database name my $database = $config->{ database } || lc( $ENV{ MOJO_APP } ); # assemble my $dsn = sprintf 'dbi:%s:database=%s', $driver, $database; $dsn .= ';host=' . $config->{ host } if $config->{ host }; $dsn .= ';port=' . $config->{ port } if $config->{ port }; } # database (DBI) connection arguments $self->connection_args( [ $config->{ dsn }, $config->{ username }, $config->{ password }, $config->{ options } || {} ] ); # log debug message $app->log->debug( 'Connecting database using: ' . $app->dumper( $self->connection_args ) ); # connect $self->dbh( DBI->connect( @{ $self->connection_args } ) ); # raise error (for case, when "RaiseError" option is not set) confess qq|Can't connect database| unless $self->dbh; # register helper $app->helper( database => sub { $self } ); return; } sub save_with_random_name { my ( $self, $content, $is_public ) = @_; # create statement handler my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?)' ); # execute $sth->execute( $content, $is_public ); # register_plan returns plan id my @row = $sth->fetchrow_array; # finish $sth->finish; # return plan id return $row[ 0 ]; } # @depesz # - why you don't use selectrow_array (or similar)? sub get_plan { my ( $self, $plan_id ) = @_; # create statement handler my $sth = $self->dbh->prepare( 'SELECT plan FROM plans WHERE id = ?' ); # execute $sth->execute( $plan_id ); # fetch row my @row = $sth->fetchrow_array; # finish $sth->finish; # return plan return $row[ 0 ]; } sub get_public_list { my $self = shift; return $self->dbh->selectall_arrayref( 'SELECT id, to_char( entered_on, ? ) as date FROM plans WHERE is_public ORDER BY entered_on DESC', { Slice => { } }, 'YYYY-MM-DD' ); } sub get_public_list_paged { my $self = shift; # "date" to Date::Simple my $to = eval { Date::Simple->new( shift || 0 ) }; # use "now" if "date" not given/valid $to ||= Date::Simple->new( ); my $since = $to - 7; my $rs = { since => $since, to => $to, rows => [], }; # select my $rows = $self->dbh->selectall_arrayref( 'SELECT id, to_char( entered_on, ? ) as date FROM plans WHERE is_public AND entered_on::date > ?::date AND entered_on::date <= ?::date ORDER BY entered_on DESC', { Slice => { } }, 'YYYY-MM-DD', $since->as_str( '%Y-%m-%d' ), $to->as_str( '%Y-%m-%d' ) ); $rs->{ next_date } = ( $to + 7 )->as_str( '%Y-%m-%d' ); $rs->{ prev_date } = ( $since )->as_str( '%Y-%m-%d' ); # set "rows" $rs->{ rows } = $rows; return $rs; } sub DESTROY { my $self = shift; # nothing to do... return unless $self->dbh; # rollback uncommited transactions $self->dbh->rollback unless $self->connection_args->[ 3 ]->{ auto_commit }; # disconnect $self->dbh->disconnect; $self->dbh( undef ); return; } 1;