You've already forked explain.depesz.com
mirror of
https://gitlab.com/depesz/explain.depesz.com.git
synced 2025-07-03 00:58:12 +02:00
175 lines
3.7 KiB
Perl
175 lines
3.7 KiB
Perl
![]() |
package Explain::Plugin::Database;
|
||
|
|
||
|
use Mojo::Base 'Mojolicious::Plugin';
|
||
|
|
||
|
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;
|
||
|
|
||
|
my $p = ( shift || '' ) =~ /\A(\d+)\z/ ? $1 : 1;
|
||
|
my $limit = ( shift || '' ) =~ /\A(\d+)\z/ ? $1 : 30;
|
||
|
|
||
|
# result, response...
|
||
|
my $rs = {
|
||
|
page => $p,
|
||
|
rows_per_page => $limit,
|
||
|
has_previous => ( $p > 1 ? 1 : 0 ),
|
||
|
has_next => 0,
|
||
|
rows => []
|
||
|
};
|
||
|
|
||
|
# OFFSET
|
||
|
my $offset = ( $p - 1 ) * $limit;
|
||
|
|
||
|
# LIMIT = $limit + 1, to see do we have "next"
|
||
|
$limit++;
|
||
|
|
||
|
# select
|
||
|
my $rows = $self->dbh->selectall_arrayref(
|
||
|
'SELECT id, to_char( entered_on, ? ) as date FROM plans WHERE is_public ORDER BY entered_on DESC LIMIT ? OFFSET ?',
|
||
|
{ Slice => { } },
|
||
|
'YYYY-MM-DD', $limit, $offset
|
||
|
);
|
||
|
|
||
|
# got results
|
||
|
if ( my $count = scalar @{ $rows || [] } ) {
|
||
|
|
||
|
# there is more (at least 1 more)
|
||
|
if ( $count == $limit ) {
|
||
|
|
||
|
# set "has_next"
|
||
|
$rs->{ has_next } = 1;
|
||
|
|
||
|
# remove "test" row
|
||
|
pop @{ $rows };
|
||
|
}
|
||
|
|
||
|
# 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;
|