File Coverage

lib/DBIx/EAV/Table.pm
Criterion Covered Total %
statement 9 67 13.4
branch 0 22 0.0
condition 0 9 0.0
subroutine 3 12 25.0
pod 6 7 85.7
total 18 117 15.3


line stmt bran cond sub pod time code
1             package DBIx::EAV::Table;
2              
3 10     10   33 use Moo;
  10         10  
  10         42  
4 10     10   1644 use SQL::Abstract;
  10         17  
  10         385  
5             use constant {
6             SQL_DEBUG => $ENV{DBIX_EAV_TRACE}
7 10     10   34 };
  10         14  
  10         7352  
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 0     0 0   my $self = shift;
19              
20 0 0 0       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 0     0 1   my ($self, $name) = @_;
28 0           foreach (@{$self->columns}) {
  0            
29 0 0         return 1 if $_ eq $name;
30             }
31 0           0;
32             }
33              
34             sub select {
35 0     0 1   my ($self, $where) = @_;
36 0   0       $where //= {};
37 0           $where = $self->_mangle_where($where);
38              
39 0           my ($stmt, @bind) = $sql->select($self->name.' AS me', $self->columns, $where);
40 0           my ($rv, $sth) = $self->_do($stmt, \@bind);
41 0           $sth;
42             }
43              
44             sub select_one {
45 0     0 1   my ($self, $where) = @_;
46 0           $self->select($where)->fetchrow_hashref;
47             }
48              
49             sub insert {
50 0     0 1   my ($self, $data) = @_;
51              
52 0 0         $data->{tenant_id} = $self->tenant_id
53             if $self->has_column('tenant_id');
54              
55 0           my ($stmt, @bind) = $sql->insert($self->name, $data);
56 0           my ($rv, $sth) = $self->_do($stmt, \@bind);
57              
58 0 0         if ($rv == 1) {
59 0   0       return $self->_dbh->last_insert_id(undef, undef, undef, undef) || 1;
60             }
61             else {
62 0           $rv;
63             }
64              
65             }
66              
67             sub update {
68 0     0 1   my ($self, $data, $where) = @_;
69 0           $where = $self->_mangle_where($where);
70              
71 0           my ($stmt, @bind) = $sql->update($self->name, $data, $where);
72 0           my ($rv, $sth) = $self->_do($stmt, \@bind);
73 0           $rv;
74             }
75              
76             sub delete {
77 0     0 1   my ($self, $where, $opts) = @_;
78 0   0       $opts //= {};
79              
80 0 0         my $stmt = $opts->{join} ? sprintf("DELETE me FROM %s AS me", $self->name)
81             : sprintf("DELETE FROM %s", $self->name);
82              
83             # JOIN
84 0 0         while (my ($table, $spec) = each %{ $opts->{join} || {} }) {
  0            
85              
86 0           my ($join_criteria, @bind) = $sql->where($spec);
87 0           while ( (my $offset = index($join_criteria, '?')) > -1) {
88 0           my $val = shift @bind;
89 0           substr($join_criteria, $offset, 1, $val);
90             }
91 0           $join_criteria =~ s/^\s*WHERE//;
92 0           $join_criteria =~ s/\btheir\./$table./g;
93 0           $stmt .= " INNER JOIN $table ON $join_criteria";
94             }
95              
96             # WHERE
97 0           my ($where_part, @bind);
98 0 0         if ($where) {
99 0           $where = $self->_mangle_where($where);
100 0           ($where_part, @bind) = $sql->where($where);
101 0           $stmt .= " $where_part";
102             }
103              
104 0           my ($rv, $sth) = $self->_do($stmt, \@bind);
105 0           $rv;
106             }
107              
108             sub _mangle_where {
109 0     0     my ($self, $where) = @_;
110              
111 0 0         return $where unless $self->has_column('tenant_id');
112              
113 0 0         if (ref $where eq 'HASH') {
114 0           $where->{tenant_id} = $self->tenant_id;
115             }
116             else {
117 0           $where = { -and => [ tenant_id => $self->tenant_id, $where ] };
118             }
119              
120 0           $where;
121             }
122              
123              
124              
125             sub _do {
126 0     0     my ($self, $stmt, $bind) = @_;
127              
128 0           if (SQL_DEBUG) {
129             my $i = 0;
130             printf STDERR "$stmt: %s\n",
131             join(' ', map { $i++.'='.$_ } @$bind);
132             }
133              
134 0           my $sth = $self->_dbh->prepare($stmt);
135 0 0         my $rv = $sth->execute(ref $bind eq 'ARRAY' ? @$bind : ());
136 0 0         die $sth->errstr unless defined $rv;
137              
138 0           return ($rv, $sth);
139             }
140              
141              
142              
143              
144              
145             1;
146              
147             __END__