Created
August 10, 2020 21:16
-
-
Save preaction/4ba85579c6bea18dc8b7e2b91bb3a46e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package Yancy::Backend::DBI; | |
use Mojo::Base -base, -signatures; | |
use Yancy::Util qw( fill_brackets ); | |
use SQL::Abstract; | |
my %MAP = ( | |
# schema_name => mapping | |
# Mapping can be... | |
# { table => $table_name } # Standard SQL from SQL::Abstract | |
# { view => $view_name } # Standard SQL, no writes | |
# { select, insert, update, delete } # Custom SQL | |
# For custom SQL, there are template fields to fill: | |
# {WHERE} - where clause will go here, w/o 'WHERE' label | |
# {ORDER} - ORDER BY clause will go here, w/o 'ORDER BY' label | |
# {LIMIT} - LIMIT/OFFSET clause will go here, w/o label | |
); | |
has dbh => sub { die 'dbh is required' }; | |
has schema => sub { {} }; # Overrides from the constructor | |
has sqla => sub { SQL::Abstract->new }; | |
sub new( $class, $db, $schema={} ) { | |
my $self = $class->SUPER::new( dbh => $db, schema => $schema ); | |
$self->dbh( $db ); | |
return $self; | |
} | |
sub get( $self, $schema_name, $id ) { | |
my $schema = $MAP{ $schema_name }{ schema } //= $self->read_schema( $schema_name ); | |
my $sql = $self->_get_sql_for( | |
$schema_name, | |
select => { | |
WHERE => $schema->{ 'x-id-field' } . ' = ?', | |
LIMIT => 1, | |
}, | |
); | |
return $self->dbh->selectrow_hashref( $sql, {}, $id ) || undef; | |
} | |
sub find( $self, $schema_name, $query, $opt ) { | |
my $map = $MAP{ $schema_name }; | |
my $schema = $map->{ schema } //= $self->read_schema( $schema_name ); | |
my ( $where, @args ) = $self->sqla->where( $query, $opt->{order_by} // {} ); | |
my $rows_sql = $map->{ select } | |
? fill_brackets( $map->{ select }, { | |
SCHEMA => $schema_name, | |
SELECT => join( ', ', keys %{ $schema->{properties} } ), | |
WHERE => $where // '1=1', | |
LIMIT => join( ', ', $opt->{limit}//2**32, $opt->{offset}//0 ), | |
} ) | |
: $self->sqla->select( | |
$schema_name, | |
[ keys %{ $schema->{ properties } } ], | |
$query, | |
$opt->{ order_by }, | |
) | |
; | |
my $total_sql = $self->_get_sql_for( | |
$schema_name, | |
select => { | |
SELECT => 'COUNT(*)', | |
WHERE => $where // '1=1', | |
LIMIT => join( ', ', 1, 0 ), | |
}, | |
); | |
return { | |
items => $self->dbh->selectall_arrayref( $rows_sql, {}, @args ), | |
total => $self->dbh->selectrow_arrayref( $total_sql, {}, @args )->[0], | |
}; | |
} | |
sub update( $self, $schema_name, $id, $data ) { | |
} | |
sub delete( $self, $schema_name, $id ) { | |
} | |
sub create( $self, $schema_name, $data ) { | |
} | |
sub _get_sql_for( $self, $schema_name, $op, $data={} ) { | |
my $map = $MAP{ $schema_name }; | |
my $sql = $map->{ $op }; | |
if ( !$sql && $map->{ table } ) { | |
$sql = $self->_get_table_sql_for( $schema_name, $op ); | |
} | |
$data{ SCHEMA } = $schema_name; | |
return fill_brackets( $sql, $data ); | |
} | |
my %TABLE_SQL = ( | |
select => q{ | |
SELECT {SELECT} FROM {SCHEMA} WHERE {WHERE} ORDER BY {ORDER} LIMIT {LIMIT} | |
}, | |
); | |
sub _get_table_sql_for( $self, $op ) { | |
return $TABLE_SQL{ $op }; | |
} | |
1; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment