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   33 use Moo;
  10         11  
  10         40  
4 10     10   1588 use SQL::Abstract;
  10         19  
  10         406  
5             use constant {
6             SQL_DEBUG => $ENV{DBIX_EAV_TRACE}
7 10     10   40 };
  10         8  
  10         7431  
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 108     108 0 52570 my $self = shift;
19              
20 108 50 66     230 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 1099     1099 1 1034 my ($self, $name) = @_;
28 1099         884 foreach (@{$self->columns}) {
  1099         2302  
29 3856 100       6076 return 1 if $_ eq $name;
30             }
31 961         3485 0;
32             }
33              
34             sub select {
35 468     468 1 730 my ($self, $where) = @_;
36 468   50     830 $where //= {};
37 468         672 $where = $self->_mangle_where($where);
38              
39 468         2152 my ($stmt, @bind) = $sql->select($self->name.' AS me', $self->columns, $where);
40 468         89384 my ($rv, $sth) = $self->_do($stmt, \@bind);
41 468         7325 $sth;
42             }
43              
44             sub select_one {
45 459     459 1 1414 my ($self, $where) = @_;
46 459         680 $self->select($where)->fetchrow_hashref;
47             }
48              
49             sub insert {
50 475     475 1 5777 my ($self, $data) = @_;
51              
52 475 100       735 $data->{tenant_id} = $self->tenant_id
53             if $self->has_column('tenant_id');
54              
55 475         1396 my ($stmt, @bind) = $sql->insert($self->name, $data);
56 475         80366 my ($rv, $sth) = $self->_do($stmt, \@bind);
57              
58 475 50       964 if ($rv == 1) {
59 475   50     6934 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 736 my ($self, $data, $where) = @_;
69 3         8 $where = $self->_mangle_where($where);
70              
71 3         16 my ($stmt, @bind) = $sql->update($self->name, $data, $where);
72 3         657 my ($rv, $sth) = $self->_do($stmt, \@bind);
73 3         33 $rv;
74             }
75              
76             sub delete {
77 109     109 1 1081 my ($self, $where, $opts) = @_;
78 109   50     364 $opts //= {};
79              
80 109 50       460 my $stmt = $opts->{join} ? sprintf("DELETE me FROM %s AS me", $self->name)
81             : sprintf("DELETE FROM %s", $self->name);
82              
83             # JOIN
84 109 50       97 while (my ($table, $spec) = each %{ $opts->{join} || {} }) {
  109         503  
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 109         122 my ($where_part, @bind);
98 109 100       168 if ($where) {
99 45         73 $where = $self->_mangle_where($where);
100 45         118 ($where_part, @bind) = $sql->where($where);
101 45         4571 $stmt .= " $where_part";
102             }
103              
104 109         191 my ($rv, $sth) = $self->_do($stmt, \@bind);
105 109         1139 $rv;
106             }
107              
108             sub _mangle_where {
109 516     516   467 my ($self, $where) = @_;
110              
111 516 100       710 return $where unless $self->has_column('tenant_id');
112              
113 88 50       199 if (ref $where eq 'HASH') {
114 88         169 $where->{tenant_id} = $self->tenant_id;
115             }
116             else {
117 0         0 $where = { -and => [ tenant_id => $self->tenant_id, $where ] };
118             }
119              
120 88         114 $where;
121             }
122              
123              
124              
125             sub _do {
126 1149     1149   1289 my ($self, $stmt, $bind) = @_;
127              
128 1149         852 if (SQL_DEBUG) {
129             my $i = 0;
130             printf STDERR "$stmt: %s\n",
131             join(' ', map { $i++.'='.$_ } @$bind);
132             }
133              
134 1149         5835 my $sth = $self->_dbh->prepare($stmt);
135 1149 50       85626 my $rv = $sth->execute(ref $bind eq 'ARRAY' ? @$bind : ());
136 1149 50       2640 die $sth->errstr unless defined $rv;
137              
138 1149         2380 return ($rv, $sth);
139             }
140              
141              
142              
143              
144              
145             1;
146              
147             __END__