TagIndex.pm 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package Trog::SQLite::TagIndex;
  2. use strict;
  3. use warnings;
  4. no warnings 'experimental';
  5. use feature qw{signatures};
  6. use List::Util qw{uniq};
  7. use Trog::SQLite;
  8. =head1 Trog::SQLite::TagIndex
  9. An SQLite3 index of posts by tag.
  10. Used to speed up the flat-file data model.
  11. =head1 FUNCTIONS
  12. =cut
  13. sub posts_for_tags (@tags) {
  14. my $dbh = _dbh();
  15. my $clause = @tags ? "WHERE tag IN (".join(',' ,(map {'?'} @tags)).")" : '';
  16. my $rows = $dbh->selectall_arrayref("SELECT id FROM posts $clause",{ Slice => {} }, @tags);
  17. return () unless ref $rows eq 'ARRAY' && @$rows;
  18. return map { $_->{id} } @$rows;
  19. }
  20. sub add_post ($post,$data_obj) {
  21. my $dbh = _dbh();
  22. return build_index($data_obj,[$post]);
  23. }
  24. sub remove_post ($post) {
  25. my $dbh = _dbh();
  26. return $dbh->do("DELETE FROM posts_index WHERE post_id=?", undef, $post->{id});
  27. }
  28. sub build_index($data_obj,$posts=[]) {
  29. my $dbh = _dbh();
  30. $posts = $data_obj->read({ limit => 0, acls => ['admin'] }) unless @$posts;
  31. my @tags = uniq map { @{$_->{tags}} } @$posts;
  32. Trog::SQLite::bulk_insert($dbh,'tag', ['name'], 'IGNORE', @tags);
  33. my $t = $dbh->selectall_hashref("SELECT id,name FROM tag", 'name');
  34. foreach my $k (keys(%$t)) { $t->{$k} = $t->{$k}->{id} };
  35. Trog::SQLite::bulk_insert($dbh,'posts_index',[qw{post_id tag_id}], 'IGNORE', map {
  36. my $subj = $_;
  37. map { ( $subj->{id}, $t->{$_} ) } @{$subj->{tags}}
  38. } @$posts );
  39. }
  40. # Ensure the db schema is OK, and give us a handle
  41. sub _dbh {
  42. my $file = 'schema/flatfile.schema';
  43. my $dbname = "data/posts.db";
  44. return Trog::SQLite::dbh($file,$dbname);
  45. }
  46. 1;