File Coverage

blib/lib/Data/Mapper/Adapter/DBI.pm
Criterion Covered Total %
statement 30 73 41.1
branch 0 16 0.0
condition 0 2 0.0
subroutine 10 19 52.6
pod 0 8 0.0
total 40 118 33.9


line stmt bran cond sub pod time code
1             package Data::Mapper::Adapter::DBI;
2 1     1   1222 use strict;
  1         3  
  1         36  
3 1     1   5 use warnings;
  1         76  
  1         150  
4 1     1   14 use parent qw(Data::Mapper::Adapter);
  1         2  
  1         8  
5              
6 1     1   80 use Carp ();
  1         2  
  1         21  
7 1     1   1117 use Data::Dumper ();
  1         13583  
  1         27  
8              
9 1     1   1019 use SQL::Maker;
  1         16952  
  1         40  
10 1     1   1198 use DBIx::Inspector;
  1         17250  
  1         46  
11              
12 1     1   9 use Data::Mapper::Schema;
  1         2  
  1         1073  
13              
14             sub create {
15             my ($self, $table, $values) = @_;
16             my ($sql, @binds) = $self->sql->insert($table, $values);
17              
18             $self->execute($sql, @binds);
19              
20             my $schema = $self->schemata->{$table};
21             my $primary_keys = $schema->primary_keys;
22             my $key = $primary_keys->[0];
23              
24             if (scalar @$primary_keys == 1 && !defined $values->{$key}) {
25             $values->{$key} = $self->last_insert_id($table);
26             }
27              
28             $values;
29             }
30              
31             sub find {
32             my ($self, $table, $where, $options) = @_;
33             my ($sql, @binds) = $self->select($table, $where, $options);
34             my $sth = $self->execute($sql, @binds);
35              
36             $sth->fetchrow_hashref;
37             }
38              
39             sub search {
40             my ($self, $table, $where, $options) = @_;
41             my ($sql, @binds) = $self->select($table, $where, $options);
42             my $sth = $self->execute($sql, @binds);
43              
44             my @result;
45             while (my $row = $sth->fetchrow_hashref) {
46             push @result, $row;
47             }
48              
49             \@result;
50             }
51              
52             sub update {
53             my ($self, $table, $set, $where) = @_;
54             my ($sql, @binds) = $self->sql->update($table, $set, $where);
55              
56             $self->execute($sql, @binds);
57             }
58              
59             sub delete {
60             my ($self, $table, $where) = @_;
61             my ($sql, @binds) = $self->sql->delete($table, $where);
62              
63             $self->execute($sql, @binds);
64             }
65              
66             sub schemata {
67 0     0 0   my $self = shift;
68              
69 0 0         if (!defined $self->{schemata}) {
70 0           $self->{schemata} = {};
71              
72 0           for my $table ($self->inspector->tables) {
73 0           $self->{schemata}{$table->name} = Data::Mapper::Schema->new({
74             table => $table->name,
75 0           primary_keys => [ map { $_->name } $table->primary_key ],
76 0           columns => [ map { $_->name } $table->columns ],
77             });
78             }
79             }
80              
81 0           $self->{schemata};
82             }
83              
84             ### PRIVATE_METHODS ###
85              
86             sub sql {
87 0     0 0   my $self = shift;
88              
89 0 0         if (!defined $self->{sql}) {
90 0           $self->{sql} = SQL::Maker->new(driver => $self->driver->{Driver}{Name});
91             }
92              
93 0           $self->{sql};
94             }
95              
96             sub inspector {
97 0     0 0   my $self = shift;
98              
99 0 0         if (!defined $self->{inspector}) {
100 0           $self->{inspector} = DBIx::Inspector->new(dbh => $self->driver);
101             }
102              
103 0           $self->{inspector};
104             }
105              
106             sub select {
107 0     0 0   my ($self, $table, $where, $options) = @_;
108 0   0       my $fields = ($options || {})->{fields} || ['*'];
109              
110 0           $self->sql->select($table, $fields, $where, $options);
111             }
112              
113             sub execute {
114 0     0 0   my ($self, $sql, @binds) = @_;
115 0           my $sth;
116              
117 0           eval {
118 0           $sth = $self->driver->prepare($sql);
119 0           $sth->execute(@binds);
120             };
121              
122 0 0         if ($@) {
123 0           $self->handle_error($sql, \@binds, $@);
124             }
125              
126 0           $sth;
127             }
128              
129             sub handle_error {
130 0     0 0   my ($self, $sql, $bind, $error) = @_;
131 0           $sql =~ s/\n/\n /gm;
132              
133 0           Carp::croak sprintf <<"TRACE", $error, $sql, Data::Dumper::Dumper($bind);
134             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
135             @@@@@ Data::Mapper Exception @@@@@
136             Reason : %s
137             SQL : %s
138             BIND : %s
139             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
140             TRACE
141             }
142              
143             sub last_insert_id {
144 0     0 0   my ($self, $table) = @_;
145 0           my $driver = $self->driver->{Driver}{Name};
146 0           my $last_insert_id;
147              
148 0 0         if ($driver eq 'mysql') {
    0          
    0          
149 0           $last_insert_id = $self->dbh->{mysql_insertid};
150             }
151             elsif ($driver eq 'Pg') {
152 0           $last_insert_id = $self->driver->last_insert_id(
153             undef, undef, undef, undef, {
154             sequence => join('_', $table, 'id', 'seq')
155             }
156             );
157             }
158             elsif ($driver eq 'SQLite') {
159 0           $last_insert_id = $self->driver->func('last_insert_rowid');
160             }
161              
162 0           $last_insert_id;
163             }
164              
165             sub check_table {
166 0     0 0   my ($self, $table) = @_;
167 0 0         $self->schemata->{$table} or Carp::croak("no such table: $table");
168             }
169              
170             {
171 1     1   7 no strict 'refs';
  1         2  
  1         50  
172 1     1   5 no warnings 'redefine';
  1         2  
  1         151  
173              
174             for my $method (qw(create find search update delete)) {
175             my $original = \&$method;
176              
177             *{__PACKAGE__."\::$method"} = sub {
178 0     0     my ($self, $table) = @_;
179 0           $self->check_table($table);
180 0           $original->(@_);
181             };
182             }
183             }
184              
185             !!1;