File Coverage

blib/lib/Aniki.pm
Criterion Covered Total %
statement 315 394 79.9
branch 108 170 63.5
condition 25 39 64.1
subroutine 70 90 77.7
pod 28 44 63.6
total 546 737 74.0


line stmt bran cond sub pod time code
1             package Aniki;
2 27     27   2217700 use 5.014002;
  27         121  
3              
4 27     27   10036 use namespace::autoclean;
  27         376662  
  27         148  
5 27     27   2423 use Mouse v2.4.5;
  27         24442  
  27         227  
6              
7 27     27   26245 use Module::Load ();
  27         26056  
  27         584  
8 27     27   10364 use Aniki::Filter;
  27         2855  
  27         1123  
9 27     27   12639 use Aniki::Handler;
  27         3011  
  27         1261  
10 27     27   13865 use Aniki::Row;
  27         2380  
  27         970  
11 27     27   12023 use Aniki::Result::Collection;
  27         2207  
  27         1064  
12 27     27   11059 use Aniki::Schema;
  27         2274  
  27         1160  
13 27     27   12866 use Aniki::QueryBuilder;
  27         132  
  27         1007  
14 27     27   10387 use Aniki::QueryBuilder::Canonical;
  27         99  
  27         1191  
15              
16             our $VERSION = '1.05';
17              
18 27     27   11210 use SQL::Maker::SQLType qw/sql_type/;
  27         10534  
  27         1972  
19 27     27   12490 use Class::Inspector;
  27         71200  
  27         1117  
20 27     27   299 use Carp qw/croak confess/;
  27         81  
  27         1859  
21 27     27   205 use Try::Tiny;
  27         73  
  27         1671  
22 27     27   206 use Scalar::Util qw/blessed/;
  27         69  
  27         1286  
23 27     27   13313 use String::CamelCase qw/camelize/;
  27         13400  
  27         1649  
24 27     27   10573 use SQL::NamedPlaceholder qw/bind_named/;
  27         41469  
  27         204  
25              
26       0     sub _noop {}
27              
28             around BUILDARGS => sub {
29             my $orig = shift;
30             my $class = shift;
31             my %args = (@_ == 1 && ref $_[0] eq 'HASH') ? %{$_[0]} : @_;
32              
33             if (not exists $args{handler}) {
34             my $connect_info = delete $args{connect_info} or confess 'Attribute (connect_info) is required';
35             my $on_connect_do = delete $args{on_connect_do};
36             my $on_disconnect_do = delete $args{on_disconnect_do};
37             my $trace_query = delete $args{trace_query} || 0;
38             my $trace_ignore_if = delete $args{trace_ignore_if} || \&_noop;
39             $args{handler} = $class->handler_class->new(
40             connect_info => $connect_info,
41             on_connect_do => $on_connect_do,
42             on_disconnect_do => $on_disconnect_do,
43             trace_query => $trace_query,
44             trace_ignore_if => $trace_ignore_if,
45             );
46             }
47              
48             return $class->$orig(\%args);
49             };
50              
51             has handler => (
52             is => 'ro',
53             required => 1,
54             );
55              
56             has suppress_row_objects => (
57             is => 'rw',
58             default => 0,
59             );
60              
61             has suppress_result_objects => (
62             is => 'rw',
63             default => 0,
64             );
65              
66             sub _database2driver {
67 56     56   925 my ($class, $database) = @_;
68 56         287 state $map = {
69             MySQL => 'mysql',
70             PostgreSQL => 'Pg',
71             SQLite => 'SQLite',
72             Oracle => 'Oracle',
73             DB2 => 'DB2',
74             };
75 56         195 return $map->{$database};
76             }
77              
78 0     0 1 0 sub schema { croak 'This is abstract method. (required to call setup method before call it)' }
79 0     0 1 0 sub query_builder { croak 'This is abstract method. (required to call setup method before call it)' }
80 0     0 1 0 sub filter { croak 'This is abstract method. (required to call setup method before call it)' }
81 0     0 0 0 sub last_insert_id { croak 'This is abstract method. (required to call setup method before call it)' }
82 0     0 1 0 sub root_row_class { croak 'This is abstract method. (required to call setup method before call it)' }
83 0     0 1 0 sub guess_row_class { croak 'This is abstract method. (required to call setup method before call it)' }
84 0     0 1 0 sub root_result_class { croak 'This is abstract method. (required to call setup method before call it)' }
85 0     0 1 0 sub guess_result_class { croak 'This is abstract method. (required to call setup method before call it)' }
86 24     24 0 345 sub handler_class { 'Aniki::Handler' }
87              
88             # You can override this method on your application.
89 403     403 1 1591 sub use_prepare_cached { 1 }
90 28     28 1 546 sub use_strict_query_builder { 1 }
91              
92             sub setup {
93 28     28 1 91746 my ($class, %args) = @_;
94              
95             # schema
96 28 50       193 if (my $schema_class = $args{schema}) {
97 28 50       314 Module::Load::load($schema_class) unless Class::Inspector->loaded($schema_class);
98              
99 28         258263 my $schema = Aniki::Schema->new(schema_class => $schema_class);
100 28     358   534 $class->meta->add_method(schema => sub { $schema });
  358     358   50244  
        8      
        8      
101             }
102             else {
103 0         0 croak 'schema option is required.';
104             }
105              
106             # filter
107 28 50       1285 if (my $filter_class = $args{filter}) {
108 28 100       364 Module::Load::load($filter_class) unless Class::Inspector->loaded($filter_class);
109              
110 28         800 my $filter = $filter_class->instance();
111 28     375   212 $class->meta->add_method(filter => sub { $filter });
  375         1591  
112             }
113             else {
114 0         0 my $filter = Aniki::Filter->new;
115 0     375   0 $class->meta->add_method(filter => sub { $filter });
  0         0  
116             }
117              
118             # handler
119 28 50       836 if (my $handler_class = $args{handler}) {
120 0 0       0 Module::Load::load($handler_class) unless Class::Inspector->loaded($handler_class);
121 0     0   0 $class->meta->add_method(handler_class => sub { $handler_class });
  0         0  
122             }
123              
124             # last_insert_id
125             {
126 28         133 my $driver = lc $class->_database2driver($class->schema->database);
127 28 50       539 my $method = $class->can("_fetch_last_insert_id_from_$driver") or Carp::croak "Don't know how to get last insert id for $driver";
128 28         163 $class->meta->add_method(last_insert_id => $method);
129             }
130              
131             # query_builder
132             {
133 28 50       66 my $query_builder_class = $class->use_prepare_cached ? 'Aniki::QueryBuilder::Canonical' : 'Aniki::QueryBuilder';
  28         201  
134 28 50       131 if ($args{query_builder}) {
135 0 0       0 Module::Load::load($args{query_builder}) unless Class::Inspector->loaded($args{query_builder});
136 0         0 $query_builder_class = $args{query_builder};
137             }
138 28         118 my $driver = $class->_database2driver($class->schema->database);
139 28         260 my $query_builder = $query_builder_class->new(driver => $driver, strict => $class->use_strict_query_builder);
140 28     174   1164 $class->meta->add_method(query_builder => sub { $query_builder });
  174         913  
141             }
142              
143             # row
144             {
145 28         559 my $root_row_class = 'Aniki::Row';
  28         76  
146 28     174   130 my $guess_row_class = sub { $root_row_class };
  0         0  
147 28 50       136 if ($args{row}) {
148 28 100       224 Module::Load::load($args{row}) unless Class::Inspector->loaded($args{row});
149 28         26580 $root_row_class = $args{row};
150              
151 28         80 my %table_row_class;
152             $guess_row_class = sub {
153 85     85   237 my $table_name = $_[1];
154             return $table_row_class{$table_name} //= try {
155 25         1819 my $table_row_class = sprintf '%s::%s', $root_row_class, camelize($table_name);
156 25         678 Module::Load::load($table_row_class);
157 20         40637 return $table_row_class;
158             } catch {
159 5 50       1779 die $_ unless /\A\QCan't locate/imo;
160 5         63 return $root_row_class;
161 85   66     909 };
162 28         185 };
163             }
164 28     85   260 $class->meta->add_method(root_row_class => sub { $root_row_class });
  0         0  
165 28         680 $class->meta->add_method(guess_row_class => $guess_row_class);
166             }
167              
168             # result
169             {
170 28         638 my $root_result_class = 'Aniki::Result::Collection';
  28         473  
  28         83  
171 28     77   127 my $guess_result_class = sub { $root_result_class };
  77         204  
172 28 50       145 if ($args{result}) {
173 0 0       0 Module::Load::load($args{result}) unless Class::Inspector->loaded($args{result});
174 0         0 $root_result_class = $args{result};
175              
176 0         0 my %table_result_class;
177             $guess_result_class = sub {
178 0     77   0 my $table_name = $_[1];
179             return $table_result_class{$table_name} //= try {
180 0         0 my $table_result_class = sprintf '%s::%s', $root_result_class, camelize($table_name);
181 0         0 Module::Load::load($table_result_class);
182 0         0 return $table_result_class;
183             } catch {
184 0 0       0 die $_ unless /\A\QCan't locate/imo;
185 0         0 return $root_result_class;
186 0   0     0 };
187 0         0 };
188             }
189              
190 28     25   127 $class->meta->add_method(root_result_class => sub { $root_result_class });
  0         0  
191 28         584 $class->meta->add_method(guess_result_class => $guess_result_class);
192             }
193             }
194              
195             sub preload_all_row_classes {
196 0     5 1 0 my $class = shift;
197 0         0 for my $table ($class->schema->get_tables) {
198 0         0 $class->guess_row_class($table->name);
199             }
200             }
201              
202             sub preload_all_result_classes {
203 0     0 1 0 my $class = shift;
204 0         0 for my $table ($class->schema->get_tables) {
205 0         0 $class->guess_result_class($table->name);
206             }
207             }
208              
209             sub dbh {
210 433     433 1 798 my $self = shift;
211             # (for mysql)
212             # XXX: `DBIx::Handler#dbh` send a ping to mysql.
213             # But, It removes `$dbh->{mysql_insertid}`.
214 433 100       1941 return $self->{_context} if exists $self->{_context};
215 338         1284 return $self->handler->dbh;
216             }
217              
218             sub insert {
219 66     66 1 321 my ($self, $table_name, $row, $opt) = @_;
220 66 100       422 $row = $self->filter_on_insert($table_name, $row) unless $opt->{no_filter};
221              
222 66         212 my $table = $self->schema->get_table($table_name);
223 66 50       368 $row = $self->_bind_sql_type_to_args($table, $row) if $table;
224              
225 66         273 my ($sql, @bind) = $self->query_builder->insert($table_name, $row, $opt);
226 66         10793 $self->execute($sql, @bind);
227 66         397 return;
228             }
229              
230             sub filter_on_insert {
231 99     99 0 238 my ($self, $table_name, $row) = @_;
232 99         314 $row = $self->filter->apply_trigger(insert => $table_name, $row);
233 99         248 return $self->filter->deflate_row($table_name, $row);
234             }
235              
236             sub update {
237 13     13 1 2417 my ($self, $table_name, $set, $where, $opt) = @_;
238              
239             # migrate for ($self, $row, $set, $opt)
240 13 100 66     161 if (blessed $_[1] && $_[1]->isa('Aniki::Row')) {
241 11         32 my $row = $_[1];
242 11         47 $table_name = $row->table_name;
243 11         30 $set = $_[2];
244 11         64 $where = $self->_where_row_cond($row->table, $row->row_data);
245 11         34 $opt = $_[3];
246             }
247              
248 13 100 100     683 croak '(Aniki#update) `set` is required for update ("SET" parameter)' unless $set && %$set;
249 9 100       168 croak '(Aniki#update) `where` condition must be a reference' unless ref $where;
250              
251 8 100       50 $set = $self->filter_on_update($table_name, $set) unless $opt->{no_filter};
252              
253 8         35 my $table = $self->schema->get_table($table_name);
254 8 50       38 if ($table) {
255 8         59 $set = $self->_bind_sql_type_to_args($table, $set);
256 8         33 $where = $self->_bind_sql_type_to_args($table, $where);
257             }
258              
259 8         48 my ($sql, @bind) = $self->query_builder->update($table_name, $set, $where);
260 8         2913 return $self->execute($sql, @bind)->rows;
261             }
262              
263             sub update_and_fetch_row {
264 5     5 1 9127 my ($self, $row, $set) = @_;
265 5 100 66     223 croak '(Aniki#update_and_fetch_row) condition must be a Aniki::Row object.'
266             unless blessed $row && $row->isa('Aniki::Row');
267              
268 4         22 my $emulated_row_data = $self->_update_and_emulate_row_data($row, $set);
269              
270 3         19 my $where = $self->_where_row_cond($row->table, $emulated_row_data);
271 3         21 return $self->select($row->table_name, $where, { limit => 1, suppress_result_objects => 1 })->[0];
272             }
273              
274             sub update_and_emulate_row {
275 5     5 1 10963 my ($self, $row, $set) = @_;
276 5 100 66     239 croak '(Aniki#update_and_emulate_row) condition must be a Aniki::Row object.' unless blessed $row && $row->isa('Aniki::Row');
277              
278 4         29 my $emulated_row_data = $self->_update_and_emulate_row_data($row, $set);
279 3 100       27 return $emulated_row_data if $self->suppress_row_objects;
280              
281 2         16 return $self->guess_row_class($row->table_name)->new(
282             table_name => $row->table_name,
283             handler => $self,
284             row_data => $emulated_row_data,
285             );
286             }
287              
288             sub _update_and_emulate_row_data {
289 8     8   33 my ($self, $row, $set) = @_;
290 8         65 $set = $self->filter_on_update($row->table_name, $set);
291 8         56 $self->update($row, $set, { no_filter => 1 });
292             return {
293 6         19 %{ $row->row_data },
  6         80  
294             %$set,
295             };
296             }
297              
298             sub delete :method {
299 4     4 1 32 my $self = shift;
300 4 100 66     30 if (blessed $_[0] && $_[0]->isa('Aniki::Row')) {
301 1         11 return $self->delete($_[0]->table_name, $self->_where_row_cond($_[0]->table, $_[0]->row_data), @_);
302             }
303             else {
304 3         10 my ($table_name, $where, $opt) = @_;
305 3 100       183 croak '(Aniki#delete) `where` condition must be a reference' unless ref $where;
306              
307 2         6 my $table = $self->schema->get_table($table_name);
308 2 50       9 if ($table) {
309 2         8 $where = $self->_bind_sql_type_to_args($table, $where);
310             }
311              
312 2         7 my ($sql, @bind) = $self->query_builder->delete($table_name, $where, $opt);
313 2         363 return $self->execute($sql, @bind)->rows;
314             }
315             }
316              
317             sub filter_on_update {
318 10     10 0 37 my ($self, $table_name, $row) = @_;
319 10         43 $row = $self->filter->apply_trigger(update => $table_name, $row);
320 10         34 return $self->filter->deflate_row($table_name, $row);
321             }
322              
323             sub insert_and_fetch_id {
324 20     20 1 2601 my $self = shift;
325              
326 20         50 local $self->{_context} = $self->dbh;
327 20         749 $self->insert(@_);
328 20 50       79 return unless defined wantarray;
329              
330 20         40 my $table_name = shift;
331 20         61 return $self->last_insert_id($table_name);
332             }
333              
334             sub insert_and_fetch_row {
335 6     6 1 133 my $self = shift;
336 6         18 my $table_name = shift;
337 6         14 my $row_data = shift;
338              
339 6 50       26 my $table = $self->schema->get_table($table_name) or croak "$table_name is not defined in schema.";
340              
341 6         22 local $self->{_context} = $self->dbh;
342              
343 6         229 $self->insert($table_name, $row_data, @_);
344 6 50       25 return unless defined wantarray;
345              
346 6         45 my $row = $self->select($table_name, $self->_where_row_cond($table, $row_data), { limit => 1, suppress_result_objects => 1 })->[0];
347 6 50       52 return $row if $self->suppress_row_objects;
348              
349 6         49 $row->is_new(1);
350 6         27 return $row;
351             }
352              
353             sub insert_and_emulate_row {
354 2     2 1 79 my ($self, $table_name, $row, $opt) = @_;
355              
356 2 50       15 my $table = $self->schema->get_table($table_name) or croak "$table_name is not defined in schema.";
357              
358 2         13 local $self->{_context} = $self->dbh;
359              
360 2 50       169 $row = $self->filter_on_insert($table_name, $row) unless $opt->{no_filter};
361              
362 2         28 $self->insert($table_name, $row, { %$opt, no_filter => 1 });
363 2 50       15 return unless defined wantarray;
364              
365 2         8 my %row_data;
366 2         20 for my $field ($table->get_fields) {
367 10 100       119 if (exists $row->{$field->name}) {
    100          
    50          
368 4         33 $row_data{$field->name} = $row->{$field->name};
369             }
370             elsif (defined(my $default_value = $field->default_value)) {
371 4 50       32 $row_data{$field->name} = ref $default_value eq 'SCALAR' ? undef : $default_value;
372             }
373             elsif ($field->is_auto_increment) {
374 2         18 $row_data{$field->name} = $self->last_insert_id($table_name, $field->name);
375             }
376             else {
377 0         0 $row_data{$field->name} = undef;
378             }
379             }
380 2 50       24 return \%row_data if $self->suppress_row_objects;
381 2         15 return $self->guess_row_class($table_name)->new(
382             table_name => $table_name,
383             handler => $self,
384             row_data => \%row_data,
385             is_new => 1,
386             );
387             }
388              
389             sub insert_on_duplicate {
390 0     0 1 0 my ($self, $table_name, $insert, $update) = @_;
391 0 0       0 if ($self->schema->database ne 'MySQL') {
392 0         0 Carp::croak 'Cannot use insert_on_duplicate (unsupported without MySQL)';
393             }
394              
395 0         0 $insert = $self->filter_on_insert($table_name, $insert);
396 0         0 $update = $self->filter_on_update($table_name, $update);
397              
398 0         0 my $table = $self->schema->get_table($table_name);
399 0 0       0 if ($table) {
400 0         0 $insert = $self->_bind_sql_type_to_args($table, $insert);
401 0         0 $update = $self->_bind_sql_type_to_args($table, $update);
402             }
403              
404 0         0 my ($sql, @bind) = $self->query_builder->insert_on_duplicate($table_name, $insert, $update);
405 0         0 $self->execute($sql, @bind);
406 0         0 return;
407             }
408              
409             sub insert_multi {
410 10     10 1 15106 my ($self, $table_name, $values, $opts) = @_;
411 10 100       64 return unless @$values;
412              
413 9 50       48 $opts = defined $opts ? {%$opts} : {};
414              
415 9         32 my @values = map { $self->filter_on_insert($table_name, $_) } @$values;
  33         128  
416 9 50       44 if (exists $opts->{update}) {
417 0 0       0 if ($self->schema->database ne 'MySQL') {
418 0         0 Carp::croak 'Cannot use insert_multi with update option (unsupported without MySQL)';
419             }
420 0         0 $opts->{update} = $self->filter_on_update($table_name, $opts->{update});
421             }
422              
423 9         61 my $table = $self->schema->get_table($table_name);
424 9 50       71 if ($table) {
425 9         78 $_ = $self->_bind_sql_type_to_args($table, $_) for @values;
426 9 50       37 if (exists $opts->{update}) {
427 0         0 $opts->{update} = $self->_bind_sql_type_to_args($table, $opts->{update});
428             }
429             }
430              
431 9 50       53 if ($self->schema->database eq 'MySQL') {
432 0         0 my ($sql, @bind) = $self->query_builder->insert_multi($table_name, \@values, $opts);
433 0         0 $self->execute($sql, @bind);
434             }
435             else {
436             $self->txn(sub {
437 9     9   1754 local $self->{_context} = shift;
438 9         86 $self->insert($table_name, $_, $opts) for @values;
439 9         266 });
440             }
441 9         848 return;
442             }
443              
444             sub _where_row_cond {
445 24     24   76 my ($self, $table, $row_data) = @_;
446 24 50       169 die "@{[ $table->name ]} doesn't have primary key." unless $table->primary_key;
  0         0  
447              
448             # fetch by primary key
449 24         55 my %where;
450 24         170 for my $pk ($table->primary_key->fields) {
451 24 50       316 $where{$pk->name} = exists $row_data->{$pk->name} ? $row_data->{$pk->name}
    100          
452             : $pk->is_auto_increment ? $self->last_insert_id($table->name, $pk->name)
453             : undef
454             ;
455             }
456              
457 24         120 return \%where;
458             }
459              
460             my $WILDCARD_COLUMNS = ['*'];
461              
462             sub select :method {
463 74     74 1 27484 my ($self, $table_name, $where, $opt) = @_;
464 74   50     297 $where //= {};
465 74   100     264 $opt //= {};
466              
467 74 50       255 croak '(Aniki#select) `where` condition must be a reference.' unless ref $where;
468              
469 74         239 my $table = $self->schema->get_table($table_name);
470              
471             my $columns = exists $opt->{columns} ? $opt->{columns}
472 74 50       497 : defined $table ? $table->field_names
    50          
473             : $WILDCARD_COLUMNS;
474              
475 74 50       375 $where = $self->_bind_sql_type_to_args($table, $where) if defined $table;
476              
477 74         176 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
478 74         232 my ($sql, @bind) = $self->query_builder->select($table_name, $columns, $where, $opt);
479 74         45568 return $self->select_by_sql($sql, \@bind, {
480             %$opt,
481             table_name => $table_name,
482             columns => $columns,
483             });
484             }
485              
486             sub fetch_and_attach_relay_data {
487 31     31 0 72 my ($self, $table_name, $prefetch, $rows) = @_;
488 31 50       78 return unless @$rows;
489              
490 31 50       87 $prefetch = [$prefetch] if ref $prefetch eq 'HASH';
491              
492 31         82 my $relationships = $self->schema->get_table($table_name)->get_relationships;
493 31         74 for my $key (@$prefetch) {
494 30 100 66     102 if (ref $key && ref $key eq 'HASH') {
495 5         18 my %prefetch = %$key;
496 5         15 for my $key (keys %prefetch) {
497 4         18 $self->_fetch_and_attach_relay_data($relationships, $rows, $key, $prefetch{$key});
498             }
499             }
500             else {
501 25         83 $self->_fetch_and_attach_relay_data($relationships, $rows, $key, []);
502             }
503             }
504             }
505              
506             sub _fetch_and_attach_relay_data {
507 29     29   63 my ($self, $relationships, $rows, $key, $prefetch) = @_;
508 29         95 my $relationship = $relationships->get($key);
509 29 50       70 unless ($relationship) {
510 0         0 croak "'$key' is not defined as relationship. (maybe possible typo?)";
511             }
512 29         157 $relationship->fetcher->execute($self, $rows, $prefetch);
513             }
514              
515             sub select_named {
516 3     3 1 7 my ($self, $sql, $bind, $opt) = @_;
517 3         11 return $self->select_by_sql(bind_named($sql, $bind), $opt);
518             }
519              
520             sub select_by_sql {
521 80     80 1 313 my ($self, $sql, $bind, $opt) = @_;
522 80   50     253 $opt //= {};
523              
524 80 100       324 local $self->{suppress_row_objects} = 1 if $opt->{suppress_row_objects};
525 80 100       267 local $self->{suppress_result_objects} = 1 if $opt->{suppress_result_objects};
526              
527 80 100       277 my $table_name = exists $opt->{table_name} ? $opt->{table_name} : $self->_guess_table_name($sql);
528 80 100       320 my $columns = exists $opt->{columns} ? $opt->{columns} : undef;
529 80 100       233 my $prefetch = exists $opt->{prefetch} ? $opt->{prefetch} : [];
530 80 100       304 $prefetch = [$prefetch] if ref $prefetch eq 'HASH';
531              
532 80   66     375 my $prefetch_enabled_fg = @$prefetch && !$self->suppress_row_objects && defined wantarray;
533 80 100       238 if ($prefetch_enabled_fg) {
534 8 100       13 my $txn; $txn = $self->txn_scope(caller => [caller]) unless $self->in_txn;
  8         30  
535              
536 8         583 my $sth = $self->execute($sql, @$bind);
537 8         42 my $result = $self->_fetch_by_sth($sth, $table_name, $columns);
538 8         37 $self->fetch_and_attach_relay_data($table_name, $prefetch, $result->rows);
539              
540 8 100       33 $txn->rollback if defined $txn; ## for read only
541 8         205 return $result;
542             }
543              
544 72         334 my $sth = $self->execute($sql, @$bind);
545              
546             # When the return value is never used, should not create object
547             # case example: use `FOR UPDATE` query for global locking
548 72 50       265 unless (defined wantarray) {
549 0         0 $sth->finish();
550 0         0 return;
551             }
552              
553 72         423 return $self->_fetch_by_sth($sth, $table_name, $columns);
554             }
555              
556             sub _fetch_by_sth {
557 80     80   239 my ($self, $sth, $table_name, $columns) = @_;
558 80   66     322 $columns //= $sth->{NAME};
559 80 50       293 $columns = $sth->{NAME} if $columns == $WILDCARD_COLUMNS;
560              
561 80         176 my @rows;
562              
563             my %row;
564 80         807 $sth->bind_columns(\@row{@$columns});
565 80         4563 push @rows => {%row} while $sth->fetch;
566 80         385 $sth->finish;
567              
568 80 100       477 if ($self->suppress_result_objects) {
569 11 100       94 return \@rows if $self->suppress_row_objects;
570              
571 9         41 my $row_class = $self->guess_row_class($table_name);
572             return [
573             map {
574 9         140 $row_class->new(
  9         252  
575             table_name => $table_name,
576             handler => $self,
577             row_data => $_,
578             )
579             } @rows
580             ];
581             }
582              
583 69         256 my $result_class = $self->guess_result_class($table_name);
584 69         1221 return $result_class->new(
585             table_name => $table_name,
586             handler => $self,
587             row_datas => \@rows,
588             suppress_row_objects => $self->suppress_row_objects,
589             );
590             }
591              
592             sub execute {
593 375     375 0 2254 my ($self, $sql, @bind) = @_;
594 375         2137 $sql = $self->handler->trace_query_set_comment($sql);
595              
596 375 50       5366 my $sth = $self->use_prepare_cached ? $self->dbh->prepare_cached($sql) : $self->dbh->prepare($sql);
597 375         96887 $self->_bind_to_sth($sth, \@bind);
598 375         1846 eval {
599 375         20989 $sth->execute();
600             };
601 375 50       1539 if ($@) {
602 0         0 $self->handle_error($sql, \@bind, $@);
603             }
604              
605 375         1512 return $sth;
606             }
607              
608             sub _bind_sql_type_to_args {
609 191     191   434 my ($self, $table, $args) = @_;
610              
611 191         339 my %bind_args;
612 191         305 for my $col (keys %{$args}) {
  191         535  
613             # if $args->{$col} is a ref, it is scalar ref or already
614             # sql type bined parameter. so ignored.
615 214 100       1266 if (ref $args->{$col}) {
    50          
616 83         194 $bind_args{$col} = $args->{$col};
617             }
618             elsif (my $field = $table->get_field($col)) {
619 131         672 $bind_args{$col} = sql_type(\$args->{$col}, $field->sql_data_type);
620             }
621             else {
622 0         0 $bind_args{$col} = $args->{$col};
623             }
624             }
625              
626 191         2033 return \%bind_args;
627             }
628              
629             sub _bind_to_sth {
630 375     375   918 my ($self, $sth, $bind) = @_;
631 375         1373 for my $i (keys @$bind) {
632 193         817 my $v = $bind->[$i];
633 193 100 66     1424 if (blessed $v && $v->isa('SQL::Maker::SQLType')) {
634 131         342 $sth->bind_param($i + 1, ${$v->value_ref}, $v->type);
  131         415  
635             } else {
636 62         289 $sth->bind_param($i + 1, $v);
637             }
638             }
639             }
640              
641             has _row_class_cache => (
642             is => 'rw',
643             default => sub {
644             my $self = shift;
645             my %cache = map { $_->name => undef } $self->schema->get_tables();
646             return \%cache;
647             },
648             );
649              
650             has _result_class_cache => (
651             is => 'rw',
652             default => sub {
653             my $self = shift;
654             my %cache = map { $_->name => undef } $self->schema->get_tables();
655             return \%cache;
656             },
657             );
658              
659             sub new_row_from_hashref {
660 1     1 0 30 my ($self, $table_name, $row_data) = @_;
661 1 50       9 return $row_data if $self->suppress_row_objects;
662              
663 1         5 my $row_class = $self->guess_row_class($table_name);
664 1         39 return $row_class->new(
665             table_name => $table_name,
666             handler => $self,
667             row_data => $row_data,
668             );
669             }
670              
671             sub new_collection_from_arrayref {
672 2     2 0 6490 my ($self, $table_name, $row_datas) = @_;
673 2 50       24 return $row_datas if $self->suppress_result_objects;
674              
675 2         12 my $result_class = $self->guess_result_class($table_name);
676 2         89 return $result_class->new(
677             table_name => $table_name,
678             handler => $self,
679             row_datas => $row_datas,
680             suppress_row_objects => $self->suppress_row_objects,
681             );
682             }
683              
684             sub _guess_table_name {
685 6     6   18 my ($self, $sql) = @_;
686 6 50       65 return $2 if $sql =~ /\sfrom\s+(["`]?)([\w]+)\1\s*/sio;
687 0         0 return;
688             }
689              
690             # --------------------------------------------------
691             # last_insert_id
692 0     0   0 sub _fetch_last_insert_id_from_mysql { shift->dbh->{mysql_insertid} }
693             sub _fetch_last_insert_id_from_pg {
694 0     0   0 my ($self, $table_name, $column) = @_;
695 0         0 my $dbh = $self->dbh;
696 0 0       0 return $dbh->last_insert_id(undef, undef, $table_name, undef) unless defined $column;
697              
698 0         0 my $sequence = join '_', $table_name, $column, 'seq';
699 0         0 return $dbh->last_insert_id(undef, undef, undef, undef, { sequence => $sequence });
700             }
701 28     28   80 sub _fetch_last_insert_id_from_sqlite { shift->dbh->sqlite_last_insert_rowid }
702 0     0   0 sub _fetch_last_insert_id_from_oracle { undef } ## XXX: Oracle haven't implement AUTO INCREMENT
703              
704             # --------------------------------------------------
705             # for transaction
706 1     1 1 11 sub txn_manager { shift->handler->txn_manager }
707 9     9 0 96 sub txn { shift->handler->txn(@_) }
708 8     8 0 56 sub in_txn { shift->handler->in_txn(@_) }
709 5     5 0 274 sub txn_scope { shift->handler->txn_scope(@_) }
710 0     0 0 0 sub txn_begin { shift->handler->txn_begin(@_) }
711 0     0 0 0 sub txn_rollback { shift->handler->txn_rollback(@_) }
712 0     0 0 0 sub txn_commit { shift->handler->txn_commit(@_) }
713              
714             # --------------------------------------------------
715             # error handling
716             sub handle_error {
717 0     0 0 0 my ($self, $sql, $bind, $e) = @_;
718 0         0 require Data::Dumper;
719              
720 0         0 local $Data::Dumper::Maxdepth = 2;
721 0         0 $sql =~ s/\n/\n /gm;
722 0         0 croak sprintf $self->exception_template, $e, $sql, Data::Dumper::Dumper($bind);
723             }
724              
725             sub exception_template {
726 0     0 0 0 return <<'__TRACE__';
727             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
728             @@@@@ Aniki 's Exception @@@@@
729             Reason : %s
730             SQL : %s
731             BIND : %s
732             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
733             __TRACE__
734             }
735              
736             sub DEMOLISH {
737 24     24 1 12013 my $self = shift;
738 24 50       542 $self->handler->disconnect() if $self->handler;
739             }
740              
741             __PACKAGE__->meta->make_immutable();
742             __END__
743              
744             =encoding utf-8
745              
746             =head1 NAME
747              
748             Aniki - The ORM as our great brother.
749              
750             =head1 SYNOPSIS
751              
752             use 5.014002;
753             package MyProj::DB::Schema {
754             use DBIx::Schema::DSL;
755              
756             create_table 'module' => columns {
757             integer 'id', primary_key, auto_increment;
758             varchar 'name';
759             integer 'author_id';
760              
761             add_index 'author_id_idx' => ['author_id'];
762              
763             belongs_to 'author';
764             };
765              
766             create_table 'author' => columns {
767             integer 'id', primary_key, auto_increment;
768             varchar 'name', unique;
769             };
770             };
771              
772             package MyProj::DB::Filter {
773             use Aniki::Filter::Declare;
774             use Scalar::Util qw/blessed/;
775             use Time::Moment;
776              
777             # define inflate/deflate filters in table context.
778             table author => sub {
779             inflate name => sub {
780             my $name = shift;
781             return uc $name;
782             };
783              
784             deflate name => sub {
785             my $name = shift;
786             return lc $name;
787             };
788             };
789              
790             inflate qr/_at$/ => sub {
791             my $datetime = shift;
792             $datetime =~ tr/ /T/;
793             $datetime .= 'Z';
794             return Time::Moment->from_string($datetime);
795             };
796              
797             deflate qr/_at$/ => sub {
798             my $datetime = shift;
799             return $datetime->at_utc->strftime('%F %T') if blessed $datetime and $datetime->isa('Time::Moment');
800             return $datetime;
801             };
802             };
803              
804             package MyProj::DB {
805             use Mouse v2.4.5;
806             extends qw/Aniki/;
807              
808             __PACKAGE__->setup(
809             schema => 'MyProj::DB::Schema',
810             filter => 'MyProj::DB::Filter',
811             row => 'MyProj::DB::Row',
812             );
813             };
814              
815             package main {
816             my $db = MyProj::DB->new(connect_info => ["dbi:SQLite:dbname=:memory:", "", ""]);
817             $db->execute($_) for split /;/, MyProj::DB::Schema->output;
818              
819             my $author_id = $db->insert_and_fetch_id(author => { name => 'songmu' });
820              
821             $db->insert(module => {
822             name => 'DBIx::Schema::DSL',
823             author_id => $author_id,
824             });
825             $db->insert(module => {
826             name => 'Riji',
827             author_id => $author_id,
828             });
829              
830             my $module = $db->select(module => {
831             name => 'Riji',
832             }, {
833             limit => 1,
834             })->first;
835             say '$module->name: ', $module->name; ## Riji
836             say '$module->author->name: ', $module->author->name; ## SONGMU
837              
838             my $author = $db->select(author => {
839             name => 'songmu',
840             }, {
841             limit => 1,
842             prefetch => [qw/modules/],
843             })->first;
844              
845             say '$author->name: ', $author->name; ## SONGMU
846             say 'modules[]->name: ', $_->name for $author->modules; ## DBIx::Schema::DSL, Riji
847             };
848              
849             1;
850              
851             =head1 DESCRIPTION
852              
853             Aniki is ORM.
854             Lite, but powerful.
855              
856             =head2 FEATURES
857              
858             =over 4
859              
860             =item Small & Simple
861              
862             You can read codes easily.
863              
864             =item Object mapping
865              
866             Inflates rows to L<Aniki::Result::Collection> object.
867             And inflates row to L<Aniki::Row> object.
868              
869             You can change result class, also we can change row class.
870             Aniki dispatches result/row class by table. (e.g. C<foo> table to C<MyDB::Row::Foo>)
871              
872             =item Raw SQL support
873              
874             Supports to execute raw C<SELECT> SQL and fetch rows of result.
875             Of course, Aniki can inflate to result/row also.
876              
877             =item Query builder
878              
879             Aniki includes query builder powered by L<SQL::Maker>.
880             L<SQL::Maker> is fast and secure SQL builder.
881              
882             =item Fork safe & Transaction support
883              
884             Aniki includes L<DBI> handler powered by L<DBIx::Handler>.
885              
886             =item Error handling
887              
888             Easy to handle execution errors by C<handle_error> method.
889             You can override it.
890              
891             =item Extendable
892              
893             You can extend Aniki by L<Mouse::Role>.
894             Aniki provides some default plugins as L<Mouse::Role>.
895              
896             =back
897              
898             =head2 RELATIONSHIP
899              
900             Aniki supports relationship.
901             Extracts relationship from schema class.
902              
903             Example:
904              
905             use 5.014002;
906             package MyProj::DB::Schema {
907             use DBIx::Schema::DSL;
908              
909             create_table 'module' => columns {
910             integer 'id', primary_key, auto_increment;
911             varchar 'name';
912             integer 'author_id';
913              
914             add_index 'author_id_idx' => ['author_id'];
915              
916             belongs_to 'author';
917             };
918              
919             create_table 'author' => columns {
920             integer 'id', primary_key, auto_increment;
921             varchar 'name', unique;
922             };
923             };
924              
925             A C<author> has many C<modules>.
926             So you can access C<author> row object to C<modules>.
927              
928             my $author = $db->select(author => { name => 'songmu' })->first;
929             say 'modules[]->name: ', $_->name for $author->modules; ## DBIx::Schema::DSL, Riji
930              
931             Also C<module> has a C<author>.
932             So you can access C<module> row object to C<author> also.
933              
934             my $module = $db->select(module => { name => 'Riji' })->first;
935             say "Riji's author is ", $module->author->name; ## SONGMU
936              
937             And you can pre-fetch related rows.
938              
939             my @modules = $db->select(module => {}, { prefetch => [qw/author/] });
940             say $_->name, "'s author is ", $_->author->name for @modules;
941              
942             =head1 SETUP
943              
944             Install Aniki from CPAN:
945              
946             cpanm Aniki
947              
948             And run C<install-aniki> command.
949              
950             install-aniki --lib=./lib MyApp::DB
951              
952             C<install-aniki> creates skeleton modules.
953              
954             =head1 METHODS
955              
956             =head2 CLASS METHODS
957              
958             =head3 C<setup(%args)>
959              
960             Initialize and customize Aniki class.
961             C<schema> is required. Others are optional.
962              
963             =head4 Arguments
964              
965             =over 4
966              
967             =item schema : ClassName
968              
969             =item handler : ClassName
970              
971             =item filter : ClassName
972              
973             =item row : ClassName
974              
975             =item result : ClassName
976              
977             =item query_builder : ClassName
978              
979             =back
980              
981             =head3 C<use_prepare_cached>
982              
983             If this method returns true value, Aniki uses C<preare_cached>.
984             This method returns true value default.
985             So you don't need to use C<preare_cached>, override it and return false value.
986              
987             =head3 C<use_strict_query_builder>
988              
989             If this method returns true value, Aniki enables L<SQL::Maker>'s strict mode.
990             This method returns true value default.
991             So you need to disable L<SQL::Maker>'s strict mode, override it and return false value.
992              
993             SEE ALSO: L<The JSON SQL Injection Vulnerability|http://blog.kazuhooku.com/2014/07/the-json-sql-injection-vulnerability.html>
994              
995             =head3 C<preload_all_row_classes>
996              
997             Preload all row classes.
998              
999             =head3 C<preload_all_result_classes>
1000              
1001             Preload all result classes.
1002              
1003             =head3 C<guess_result_class($table_name) : ClassName>
1004              
1005             Guesses result class by table name.
1006              
1007             =head3 C<guess_row_class($table_name) : ClassName>
1008              
1009             Guesses row class by table name.
1010              
1011             =head3 C<new(%args) : Aniki>
1012              
1013             Create instance of Aniki.
1014              
1015             =head4 Arguments
1016              
1017             =over 4
1018              
1019             =item C<handler : Aniki::Handler>
1020              
1021             Instance of Aniki::Hanlder.
1022             If this argument is given, not required to give C<connect_info> for arguments.
1023              
1024             =item C<connect_info : ArrayRef>
1025              
1026             Auguments for L<DBI>'s connect method.
1027              
1028             =item on_connect_do : CodeRef|ArrayRef[Str]|Str
1029              
1030             =item on_disconnect_do : CodeRef|ArrayRef[Str]|Str
1031              
1032             Execute SQL or CodeRef when connected/disconnected.
1033              
1034             =item trace_query : Bool
1035              
1036             Enables to inject a caller information as SQL comment.
1037             SEE ALSO: L<DBIx::Handler>
1038              
1039             =item trace_ignore_if : CodeRef
1040              
1041             Ignore to inject the SQL comment when trace_ignore_if's return value is true.
1042             SEE ALSO: L<DBIx::Handler>
1043              
1044             =item C<suppress_row_objects : Bool>
1045              
1046             If this option is true, no create row objects.
1047             Aniki's methods returns hash reference instead of row object.
1048              
1049             =item C<suppress_result_objects : Bool>
1050              
1051             If this option is true, no create result objects.
1052             Aniki's methods returns array reference instead of result object.
1053              
1054             =back
1055              
1056             =head2 INSTANCE METHODS
1057              
1058             =head3 C<select($table_name, \%where, \%opt)>
1059              
1060             Execute C<SELECT> query by generated SQL, and returns result object.
1061              
1062             my $result = $db->select(foo => { id => 1 }, { limit => 1 });
1063             # stmt: SELECT FROM foo WHERE id = ? LIMIT 1
1064             # bind: [1]
1065              
1066             =head4 Options
1067              
1068             There are the options of C<SELECT> query.
1069             See also L<SQL::Maker|https://metacpan.org/pod/SQL::Maker#opt>.
1070              
1071             And you can use there options:
1072              
1073             =over 4
1074              
1075             =item C<suppress_row_objects : Bool>
1076              
1077             If this option is true, no create row objects.
1078             This methods returns hash reference instead of row object.
1079              
1080             =item C<suppress_result_objects : Bool>
1081              
1082             If this option is true, no create result objects.
1083             This method returns array reference instead of result object.
1084              
1085             =item C<columns : ArrayRef[Str]>
1086              
1087             List for retrieving columns from database.
1088              
1089             =item C<prefetch : ArrayRef|HashRef>
1090              
1091             Pre-fetch specified related rows.
1092             See also L</"RELATIONSHIP"> section.
1093              
1094             =back
1095              
1096             =head3 C<select_named($sql, \%bind, \%opt)>
1097              
1098             =head3 C<select_by_sql($sql, \@bind, \%opt)>
1099              
1100             Execute C<SELECT> query by specified SQL, and returns result object.
1101              
1102             my $result = $db->select_by_sql('SELECT FROM foo WHERE id = ? LIMIT 1', [1]);
1103             # stmt: SELECT FROM foo WHERE id = ? LIMIT 1
1104             # bind: [1]
1105              
1106             =head4 Options
1107              
1108             You can use there options:
1109              
1110             =over 4
1111              
1112             =item C<table_name: Str>
1113              
1114             This is table name using row/result class guessing.
1115              
1116             =item C<columns: ArrayRef[Str]>
1117              
1118             List for retrieving columns from database.
1119              
1120             =item C<prefetch: ArrayRef|HashRef>
1121              
1122             Pre-fetch specified related rows.
1123             See also L</"RELATIONSHIP"> section.
1124              
1125             =back
1126              
1127             =head3 C<insert($table_name, \%values, \%opt)>
1128              
1129             Execute C<INSERT INTO> query.
1130              
1131             $db->insert(foo => { bar => 1 });
1132             # stmt: INSERT INTO foo (bar) VALUES (?)
1133             # bind: [1]
1134              
1135              
1136             =head3 C<insert_and_fetch_id($table_name, \%values, \%opt)>
1137              
1138             Execute C<INSERT INTO> query, and returns C<last_insert_id>.
1139              
1140             my $id = $db->insert_and_fetch_id(foo => { bar => 1 });
1141             # stmt: INSERT INTO foo (bar) VALUES (?)
1142             # bind: [1]
1143              
1144             =head3 C<insert_and_fetch_row($table_name, \%values, \%opt)>
1145              
1146             Execute C<INSERT INTO> query, and C<SELECT> it, and returns row object.
1147              
1148             my $row = $db->insert_and_fetch_row(foo => { bar => 1 });
1149             # stmt: INSERT INTO foo (bar) VALUES (?)
1150             # bind: [1]
1151              
1152             =head3 C<insert_and_emulate_row($table_name, \%values, \%opt)>
1153              
1154             Execute C<INSERT INTO> query, and returns row object created by C<$row> and schema definition.
1155              
1156             my $row = $db->insert_and_fetch_row(foo => { bar => 1 });
1157             # stmt: INSERT INTO foo (bar) VALUES (?)
1158             # bind: [1]
1159              
1160             This method is faster than C<insert_and_fetch_row>.
1161              
1162             =head4 WARNING
1163              
1164             If you use SQL C<TRIGGER> or dynamic default value, this method don't return the correct value, maybe.
1165             In this case, you should use C<insert_and_fetch_row> instead of this method.
1166              
1167             =head3 C<insert_on_duplicate($table_name, \%insert, \%update)>
1168              
1169             Execute C<INSERT ... ON DUPLICATE KEY UPDATE> query for MySQL.
1170              
1171             my $row = $db->insert_on_duplicate(foo => { bar => 1 }, { bar => \'VALUE(bar) + 1' });
1172             # stmt: INSERT INTO foo (bar) VALUES (?) ON DUPLICATE KEY UPDATE bar = VALUE(bar) + 1
1173             # bind: [1]
1174              
1175             SEE ALSO: L<INSERT ... ON DUPLICATE KEY UPDATE Syntax|https://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html>
1176              
1177             =head3 C<insert_multi($table_name, \@values, \%opts)>
1178              
1179             Execute C<INSERT INTO ... (...) VALUES (...), (...), ...> query for MySQL.
1180             Insert multiple rows at once.
1181              
1182             my $row = $db->insert_multi(foo => [{ bar => 1 }, { bar => 2 }, { bar => 3 }]);
1183             # stmt: INSERT INTO foo (bar) VALUES (?),(?),(?)
1184             # bind: [1, 2, 3]
1185              
1186             SEE ALSO: L<INSERT Syntax|https://dev.mysql.com/doc/refman/5.6/en/insert.html>
1187              
1188             =head3 C<update($table_name, \%set, \%where)>
1189              
1190             Execute C<UPDATE> query, and returns changed rows count.
1191              
1192             my $count = $db->update(foo => { bar => 2 }, { id => 1 });
1193             # stmt: UPDATE foo SET bar = ? WHERE id = ?
1194             # bind: [2, 1]
1195              
1196             =head3 C<update($row, \%set)>
1197              
1198             Execute C<UPDATE> query, and returns changed rows count.
1199              
1200             my $row = $db->select(foo => { id => 1 }, { limit => 1 })->first;
1201             my $count = $db->update($row => { bar => 2 });
1202             # stmt: UPDATE foo SET bar = ? WHERE id = ?
1203             # bind: [2, 1]
1204              
1205             =head3 C<update_and_fetch_row($row, \%set)>
1206              
1207             Execute C<UPDATE> query, and C<SELECT> it, and returns row object.
1208              
1209             my $row = $db->select(foo => { id => 1 }, { limit => 1 })->first;
1210             my $new_row = $db->update_and_fetch_row($row => { bar => 2 });
1211             # stmt: UPDATE foo SET bar = ? WHERE id = ?
1212             # bind: [2, 1]
1213              
1214             =head3 C<update_and_emulate_row($row, \%set)>
1215              
1216             Execute C<UPDATE> query, and returns row object created by C<$row> and C<%set>.
1217              
1218             my $row = $db->select(foo => { id => 1 }, { limit => 1 })->first;
1219             my $new_row = $db->update_and_emulate_row($row => { bar => 2 });
1220             # stmt: UPDATE foo SET bar = ? WHERE id = ?
1221             # bind: [2, 1]
1222              
1223             This method is faster than C<update_and_fetch_row>.
1224              
1225             =head4 WARNING
1226              
1227             If you use SQL C<TRIGGER> or C<AutoCommit>, this method don't return the correct value, maybe.
1228             In this case, you should use C<update_and_fetch_row> instead of this method.
1229              
1230             =head3 C<delete($table_name, \%where)>
1231              
1232             Execute C<DELETE> query, and returns changed rows count.
1233              
1234             my $count = $db->delete(foo => { id => 1 });
1235             # stmt: DELETE FROM foo WHERE id = ?
1236             # bind: [1]
1237              
1238             =head3 C<delete($row)>
1239              
1240             Execute C<DELETE> query, and returns changed rows count.
1241              
1242             my $row = $db->select(foo => { id => 1 }, { limit => 1 })->first;
1243             my $count = $db->delete($row);
1244             # stmt: DELETE foo WHERE id = ?
1245             # bind: [1]
1246              
1247             =head2 ACCESSORS
1248              
1249             =over 4
1250              
1251             =item C<schema : Aniki::Schema>
1252              
1253             =item C<filter : Aniki::Filter>
1254              
1255             =item C<query_builder : Aniki::QueryBuilder>
1256              
1257             =item C<root_row_class : Aniki::Row>
1258              
1259             =item C<root_result_class : Aniki::Result>
1260              
1261             =item C<connect_info : ArrayRef>
1262              
1263             =item C<on_connect_do : CodeRef|ArrayRef[Str]|Str>
1264              
1265             =item C<on_disconnect_do : CodeRef|ArrayRef[Str]|Str>
1266              
1267             =item C<suppress_row_objects : Bool>
1268              
1269             =item C<suppress_result_objects : Bool>
1270              
1271             =item C<dbh : DBI::db>
1272              
1273             =item C<handler : Aniki::Handler>
1274              
1275             =item C<txn_manager : DBIx::TransactionManager>
1276              
1277             =back
1278              
1279             =head1 CONTRIBUTE
1280              
1281             I need to support documentation and reviewing my english.
1282             This module is developed on L<Github|http://github.com/karupanerura/Aniki>.
1283              
1284             =head1 LICENSE
1285              
1286             Copyright (C) karupanerura.
1287              
1288             This library is free software; you can redistribute it and/or modify
1289             it under the same terms as Perl itself.
1290              
1291             =head1 CONTRIBUTORS
1292              
1293             =over 2
1294              
1295             =item watanabe-yocihi
1296              
1297             =item Pine Mizune
1298              
1299             =item Syohei YOSHIDA
1300              
1301             =back
1302              
1303             =head1 AUTHOR
1304              
1305             karupanerura E<lt>karupa@cpan.orgE<gt>
1306              
1307             =cut
1308