File Coverage

lib/DBIx/EAV/Table.pm
Criterion Covered Total %
statement 58 67 86.5
branch 15 22 68.1
condition 5 9 55.5
subroutine 12 12 100.0
pod 6 7 85.7
total 96 117 82.0


line stmt bran cond sub pod time code
1             package DBIx::EAV::Table;
2              
3 10     10   58 use Moo;
  10         17  
  10         52  
4 10     10   2709 use SQL::Abstract;
  10         25  
  10         467  
5             use constant {
6             SQL_DEBUG => $ENV{DBIX_EAV_TRACE}
7 10     10   66 };
  10         16  
  10         9686  
8              
9             my $sql = SQL::Abstract->new;
10              
11             has '_dbh', is => 'ro', required => 1, init_arg => 'dbh';
12             has 'name', is => 'ro', required => 1;
13             has 'columns', is => 'ro', required => 1;
14             has 'tenant_id', is => 'ro';
15              
16              
17             sub BUILD {
18 103     103 0 75420 my $self = shift;
19              
20 103 50 66     287 die sprintf "Error instantiating table '%s': tenant_id is required!"
21             if $self->has_column('tenant_id') && !defined $self->tenant_id;
22             }
23              
24              
25              
26             sub has_column {
27 1135     1135 1 1678 my ($self, $name) = @_;
28 1135         1262 foreach (@{$self->columns}) {
  1135         2717  
29 3944 100       6649 return 1 if $_ eq $name;
30             }
31 964         2898 0;
32             }
33              
34             sub select {
35 550     550 1 1313 my ($self, $where) = @_;
36 550   50     1103 $where //= {};
37 550         1026 $where = $self->_mangle_where($where);
38              
39 550         2503 my ($stmt, @bind) = $sql->select($self->name.' AS me', $self->columns, $where);
40 550         168070 my ($rv, $sth) = $self->_do($stmt, \@bind);
41 550         10743 $sth;
42             }
43              
44             sub select_one {
45 545     545 1 2268 my ($self, $where) = @_;
46 545         1057 $self->select($where)->fetchrow_hashref;
47             }
48              
49             sub insert {
50 446     446 1 7519 my ($self, $data) = @_;
51              
52 446 100       895 $data->{tenant_id} = $self->tenant_id
53             if $self->has_column('tenant_id');
54              
55 446         1638 my ($stmt, @bind) = $sql->insert($self->name, $data);
56 446         137242 my ($rv, $sth) = $self->_do($stmt, \@bind);
57              
58 446 50       1137 if ($rv == 1) {
59 446   50     7761 return $self->_dbh->last_insert_id(undef, undef, undef, undef) || 1;
60             }
61             else {
62 0         0 $rv;
63             }
64              
65             }
66              
67             sub update {
68 3     3 1 1088 my ($self, $data, $where) = @_;
69 3         8 $where = $self->_mangle_where($where);
70              
71 3         17 my ($stmt, @bind) = $sql->update($self->name, $data, $where);
72 3         1030 my ($rv, $sth) = $self->_do($stmt, \@bind);
73 3         38 $rv;
74             }
75              
76             sub delete {
77 97     97 1 1483 my ($self, $where, $opts) = @_;
78 97   50     460 $opts //= {};
79              
80 97 50       585 my $stmt = $opts->{join} ? sprintf("DELETE me FROM %s AS me", $self->name)
81             : sprintf("DELETE FROM %s", $self->name);
82              
83             # JOIN
84 97 50       204 while (my ($table, $spec) = each %{ $opts->{join} || {} }) {
  97         586  
85              
86 0         0 my ($join_criteria, @bind) = $sql->where($spec);
87 0         0 while ( (my $offset = index($join_criteria, '?')) > -1) {
88 0         0 my $val = shift @bind;
89 0         0 substr($join_criteria, $offset, 1, $val);
90             }
91 0         0 $join_criteria =~ s/^\s*WHERE//;
92 0         0 $join_criteria =~ s/\btheir\./$table./g;
93 0         0 $stmt .= " INNER JOIN $table ON $join_criteria";
94             }
95              
96             # WHERE
97 97         252 my ($where_part, @bind);
98 97 100       214 if ($where) {
99 33         83 $where = $self->_mangle_where($where);
100 33         132 ($where_part, @bind) = $sql->where($where);
101 33         6535 $stmt .= " $where_part";
102             }
103              
104 97         271 my ($rv, $sth) = $self->_do($stmt, \@bind);
105 97         1345 $rv;
106             }
107              
108             sub _mangle_where {
109 586     586   850 my ($self, $where) = @_;
110              
111 586 100       985 return $where unless $self->has_column('tenant_id');
112              
113 122 50       321 if (ref $where eq 'HASH') {
114 122         285 $where->{tenant_id} = $self->tenant_id;
115             }
116             else {
117 0         0 $where = { -and => [ tenant_id => $self->tenant_id, $where ] };
118             }
119              
120 122         186 $where;
121             }
122              
123              
124              
125             sub _do {
126 1169     1169   2251 my ($self, $stmt, $bind) = @_;
127              
128 1169         1233 if (SQL_DEBUG) {
129             my $i = 0;
130             printf STDERR "$stmt: %s\n",
131             join(' ', map { $i++.'='.$_ } @$bind);
132             }
133              
134 1169         7171 my $sth = $self->_dbh->prepare($stmt);
135 1169 50       106288 my $rv = $sth->execute(ref $bind eq 'ARRAY' ? @$bind : ());
136 1169 50       3940 die $sth->errstr unless defined $rv;
137              
138 1169         3583 return ($rv, $sth);
139             }
140              
141              
142              
143              
144              
145             1;
146              
147             __END__