add importing support to idiotbox
[catagits/App-IdiotBox.git] / lib / App / IdiotBox / Store / SQLite.pm
CommitLineData
265c2b91 1package App::IdiotBox::Store::SQLite;
2
3use strict;
4use warnings FATAL => 'all';
5use DBIx::Data::Store;
6use DBIx::Data::Store::CRUD;
7use App::IdiotBox::DataSet;
8use Scalar::Util qw(weaken);
9
10my (%BIND, %SQL);
11
12%BIND = (
13 recent_announcements => {
14 class => {
15 inflate => sub {
16 my ($self, $obj) = @_;
17 bless($obj, 'App::IdiotBox::Announcement');
18 bless($obj->{bucket}, 'App::IdiotBox::Bucket');
19 $obj;
20 },
21 deflate => sub {
22 my ($self, $obj) = @_;
23 my %raw = %$obj;
265c2b91 24 \%raw;
25 }
26 },
27 set_over => [ 'id' ],
28 },
29 buckets => {
30 class => {
31 inflate => sub {
32 my ($self, $obj) = @_;
33 bless($obj, 'App::IdiotBox::Bucket');
34 weaken (my $weak = $obj);
35 $obj->{videos} = _bind_set('bucket_videos',
36 {
37 raw_store => $self->_store->raw_store,
ebba317f 38 implicit_arguments => { 'bucket.slug' => $obj->{slug} },
265c2b91 39 },
40 {
41 class => {
42 inflate => sub {
43 my ($self, $obj) = @_;
44 bless($obj, 'App::IdiotBox::Video');
45 weaken($obj->{bucket} = $weak);
46 $obj;
47 },
48 deflate => sub {
49 my ($self, $obj) = @_;
50 my %raw = %$obj;
51 delete $raw{bucket};
52 \%raw;
53 },
54 }
55 }
56 );
57 $obj;
58 },
59 deflate => sub {
60 my ($self, $obj) = @_;
61 my %raw = %$obj;
62 delete $raw{videos};
63 \%raw;
64 }
65 },
66 set_over => [ 'slug' ],
67 },
68 bucket_videos => {
69 set_over => [ 'slug' ]
70 },
71);
72
73%SQL = (
74 recent_announcements => {
75 select_column_order => [ qw(
76 id made_at video_count bucket.slug bucket.name bucket.video_count
77 ) ],
78 select_sql => q{
79 SELECT
80 announcement.id, announcement.made_at, COUNT(DISTINCT my_videos.slug),
81 bucket.slug, bucket.name, COUNT(DISTINCT all_videos.slug)
82 FROM
83 announcements announcement
84 JOIN buckets bucket
85 ON bucket.slug = announcement.bucket_slug
86 JOIN videos my_videos
87 ON my_videos.announcement_id = announcement.id
88 JOIN videos all_videos
89 ON all_videos.bucket_slug = announcement.bucket_slug
90 JOIN announcements all_announcements
91 ON all_announcements.bucket_slug = announcement.bucket_slug
92 GROUP BY
93 announcement.made_at, bucket.slug, bucket.name
94 HAVING
95 announcement.made_at = MAX(all_announcements.made_at)
96 ORDER BY
97 announcement.made_at DESC
98 },
ebba317f 99 insert_command_constructor => sub {
100 require DBIx::Data::Store::Command::Insert::LastInsertId;
101 my $self = shift;
102 DBIx::Data::Store::Command::Insert::LastInsertId->new(
103 id_column => 'id',
104 raw_store => $self->raw_store,
105 insert_call_command => $self->raw_store->new_call_command(@_)
106 );
107 },
108 insert_sql => q{
109 INSERT INTO announcements
110 (bucket_slug, made_at)
111 VALUES
112 (?, ?)
113 },
114 insert_argument_order => [ qw(bucket.slug made_at) ],
265c2b91 115 },
116 buckets => {
117 select_column_order => [ qw(slug name) ],
118 select_single_sql => q{
119 SELECT slug, name
120 FROM buckets
121 WHERE slug = ?
122 },
ebba317f 123 select_sql => q{
124 SELECT slug, name
125 FROM buckets
126 },
265c2b91 127 select_single_argument_order => [ 'slug' ],
128 },
129 bucket_videos => {
130 select_column_order => [ qw(slug name author details) ],
131 select_sql => q{
132 SELECT slug, name, author, details
133 FROM videos
134 WHERE bucket_slug = ?
ebba317f 135 ORDER BY name
265c2b91 136 },
ebba317f 137 select_argument_order => [ 'bucket.slug' ],
265c2b91 138 select_single_sql => q{
139 SELECT slug, name, author, details
140 FROM videos
141 WHERE bucket_slug = ? AND slug = ?
142 },
ebba317f 143 select_single_argument_order => [ qw(bucket.slug slug) ],
144 insert_sql => q{
145 INSERT INTO videos
146 (announcement_id, bucket_slug, slug, name, author, details)
147 VALUES
148 (?, ?, ?, ?, ?, '')
149 },
150 insert_argument_order => [
151 qw(announcement.id bucket.slug slug name author)
152 ],
265c2b91 153 },
154);
155
156sub bind {
157 my ($class, $idiotbox) = @_;
158 bless({ idiotbox => $idiotbox }, $class)->_bind;
159}
160
265c2b91 161sub _new_db_store {
71a02d85 162 DBIx::Data::Store->connect("dbi:SQLite:$_[1]");
265c2b91 163}
164
165sub _bind {
166 my $self = shift;
167 my $idiotbox = $self->{idiotbox};
168
71a02d85 169 my $db_store = $self->_new_db_store($idiotbox->config->{db_file});
265c2b91 170
171 foreach my $to_bind (qw(recent_announcements buckets)) {
172 $idiotbox->{$to_bind} = _bind_set($to_bind, { raw_store => $db_store });
173 }
174 $idiotbox;
175}
176
177sub _bind_set {
178 my ($type, $store_args, $set_args) = @_;
179 my $store = DBIx::Data::Store::CRUD->new({
180 %{$SQL{$type}},
181 %{$store_args},
182 });
183 return App::IdiotBox::DataSet->new({
184 %{$BIND{$type}},
185 store => $store,
186 %{$set_args||{}},
187 });
188}
189
1901;