diff --git a/lib/utils/db/query.pm b/lib/utils/db/query.pm new file mode 100644 index 0000000000000000000000000000000000000000..4175512bd33b715c432215193fb7966becd85b74 --- /dev/null +++ b/lib/utils/db/query.pm @@ -0,0 +1,170 @@ +package utils::db::query; + +use feature 'state'; +use Moose; +use FindBin; + +use lib "$FindBin::Bin/lib/"; +use utils::db; + + +has '_dbh' => ( + is => 'rw', + isa => 'HashRef', + init_arg => undef, + default => sub { state %h; return \%h; } +); + +has '_sth' => ( + is => 'rw', + isa => 'HashRef', + init_arg => undef, + default => sub { state %h; return \%h; } +); + +has '_queries' => ( + is => 'rw', + isa => 'HashRef', + init_arg => undef, + default => sub { state %h; return \%h; } +); + +sub get { + my ($self, $query) = @_; + my $chan = $query->chan; + my $result; + + if (defined $self->_queries->{$chan} and $self->_queries->{$chan} ~~ $query) { + $result = $self->_get_next($query); + } + else { + $self->_init($query); + $result = $self->_get_next($query); + } + + $self->_queries->{$chan} = $query; + return $result; +} + +sub get_rows { + my ($self, $query) = @_; + + my $dbh = utils::db::get_new_session(); + my ($request, @args) = $self->_prepare_request($query); + + my $sth = $dbh->prepare('select count(*) from ('.$request.') as TGTGTG'); + $sth->execute(@args); + + my $rows = $sth->fetch->[0]; + $sth->finish; + $dbh->commit; + $dbh->disconnect; + + return $rows; +} + +sub _get_next { + my ($self, $query) = @_; + my $chan = $query->chan; + + my $result = $self->_sth->{$chan}->fetch(); + return $result if ($result); + + # there is no more data to fetch + $self->_sth->{$chan} = undef; + $self->_dbh->{$chan}->commit(); + return undef; +} + +sub _init { + my ($self, $query) = @_; + my $chan = $query->chan; + + if (defined $self->_sth->{$chan}) { + $self->_sth->{$chan}->finish(); + } + elsif (not defined $self->_dbh->{$chan}) { + $self->_dbh->{$chan} = utils::db::get_new_session(); + } + + my ($request, @args) = $self->_prepare_request($query); + my $sth = $self->_dbh->{$chan}->prepare($request); + $sth->execute(@args); + + $self->_sth->{$query->chan} = $sth; +} + +sub _prepare_request { + my ($self, $query) = @_; + + my @words_param; + my $req; + my @args; + + foreach (@{$query->words}) { + unshift @words_param, '%'.$_.'%'; + } + + my $words_sql; + foreach (@{$query->words}) { + $words_sql .= ' and ' if ($words_sql); + $words_sql .= "concat(p.sender, ' ', p.title) like ?"; + } + + if ($query->id >= 0) { + $req = 'select p.id, p.sender, p.title, p.url, p.duration'; + $req .= ' from playbot p where id = ?'; + + @args = ($query->id); + } + elsif (@{$query->tags}) { + my @where; + + foreach my $tag (@{$query->tags}) { + unshift @where, 'p.id in (select pt.id from playbot_tags pt where pt.tag = ?)'; + } + + my $where = join ' and ' => @where; + + if ($query->is_global) { + $req = 'select p.id, p.sender, p.title, p.url, p.duration'; + $req .= ' from playbot p where '.$where; + $req .= ' and '.$words_sql if ($words_sql); + $req .= ' group by p.id order by rand()'; + + @args = (@{$query->tags}, @words_param); + } + else { + $req = 'select p.id, p.sender, p.title, p.url, p.duration'; + $req .= ' from playbot p join playbot_chan pc on p.id = pc.content'; + $req .= ' where '.$where; + $req .= ' and '.$words_sql if ($words_sql); + $req .= ' and pc.chan = ? group by p.id order by rand()'; + + @args = (@{$query->tags}, @words_param, $query->chan); + } + } + else { + if ($query->is_global) { + $req = 'select p.id, p.sender, p.title, p.url, p.duration'; + $req .= ' from playbot p'; + $req .= ' where '.$words_sql if ($words_sql); + $req .= ' group by p.id order by rand()'; + + @args = (@words_param); + } + else { + $req = 'select p.id, p.sender, p.title, p.url, p.duration'; + $req .= ' from playbot p join playbot_chan pc on p.id = pc.content'; + $req .= ' where pc.chan = ?'; + $req .= ' and '.$words_sql if ($words_sql); + $req .= ' group by p.id order by rand()'; + + @args = ($query->chan, @words_param); + } + } + + return ($req, @args); +} + +1;