File Coverage

blib/lib/EntityModel/Query/Condition.pm
Criterion Covered Total %
statement 59 69 85.5
branch 20 30 66.6
condition 1 3 33.3
subroutine 7 8 87.5
pod 6 6 100.0
total 93 116 80.1


line stmt bran cond sub pod time code
1             package EntityModel::Query::Condition;
2             {
3             $EntityModel::Query::Condition::VERSION = '0.102';
4             }
5             use EntityModel::Class {
6 16         180 _isa => [qw{EntityModel::Query::Base}],
7             'expr' => { type => 'string' },
8             'branch' => 'object'
9 16     16   11898 };
  16         32  
10 16     16   8842 no if $] >= 5.017011, warnings => "experimental::smartmatch";
  16         51  
  16         140  
11              
12             =head1 NAME
13              
14             EntityModel::Query::Condition - a condition clause for where, on etc.
15              
16             =head1 VERSION
17              
18             version 0.102
19              
20             =head1 SYNOPSIS
21              
22             =head1 DESCRIPTION
23              
24             =cut
25              
26             sub new {
27 6     6 1 11 my $class = shift;
28 6         19 my $self = bless { }, $class;
29 6 50       30 $self->branch($self->parseCondition(ref $_[0] ? (@_) : ({ @_ })));
30 6         149 return $self;
31             }
32              
33             =head2 inlineSQL
34              
35             Returns the "inline SQL" representation for this condition. See L description for more details on what this means.
36              
37             =cut
38              
39             sub inlineSQL {
40 12     12 1 48 my $self = shift;
41 12         30 return [ $self->parseBranch($self->branch) ];
42             }
43              
44             =head2 parseCondition
45              
46             An array reference expands out as follows:
47              
48             [ x => 3 ]
49              
50             =cut
51              
52             sub parseCondition {
53 6     6 1 9 my $self = shift;
54 6         7 my $data = shift;
55              
56             # Accept hashrefs, but turn them into arrayref by default.
57 6 100       22 $data = [ %$data ] if ref $data ~~ 'HASH';
58              
59 6         17 my @list = @$data;
60              
61 6         5 my @node;
62             my @tree;
63             ITEM:
64 6         15 while(@list) {
65 8         12 my $k = shift(@list);
66 8         11 my $item;
67 8 50       15 if(ref $k) {
68 0         0 $item = $self->parseCondition($k);
69             } else {
70 8         58 my ($start, $directive) = $k =~ /^(.)(.*)$/;
71             # If we have a directive such as and, or, etc. then we're switching mode
72 8 100       18 if($start eq '-') {
73 1 50       3 if($directive eq 'subquery') {
74 0         0 $item = $self->parseQuery(shift(@list));
75             } else {
76 1         3 push @node, $directive;
77 1         3 next ITEM;
78             }
79             } else {
80 7 50       27 $k = $self->quoteIdentifier($k) unless ref $k;
81 7         9 my $v = shift(@list);
82 7 100       27 if(!ref($v)) {
    50          
83 4         11 $item = [ $k, $v ];
84             } elsif(ref($v) ~~ [qw{HASH SCALAR}]) {
85 3         9 $item = [ $k, $v ];
86             } else {
87 0         0 $v = $self->parseCondition($v);
88 0         0 $item = [ $k, $v ];
89             }
90             }
91             }
92 7 100       18 if(@node) {
93 1         1 my $prev = pop(@tree);
94 1 50       4 die 'no previous item?' unless $prev;
95              
96 1         5 my $entry = {
97             op => join(' ', @node),
98             left => $prev,
99             right => $item
100             };
101 1         2 $item = $entry;
102 1         2 @node = ();
103             }
104 7         20 push @tree, $item;
105             }
106 6 50 33     50 return $tree[0] if @tree == 1 && ref $tree[0];
107 0         0 return \@tree;
108             }
109              
110             =head2 parseBranch
111              
112             For a hashref, the following three items should be in the hash:
113              
114             =over 4
115              
116             =item * left - left node of the branch, this will be recursed into as appropriate
117              
118             =item * right - right node of the branch, will be recursed as required
119              
120             =item * op - the operation to perform, such as =, and, or, etc.
121              
122             =back
123              
124             An arrayref will use the '=' operation for all entries unless the second element is
125             a hashref, in which case the key will be used as the operation and the value as the
126             RHS.
127              
128             =cut
129              
130             sub parseBranch {
131 16     16 1 52 my $self = shift;
132 16         15 my $item = shift;
133 16         15 my @query;
134 16 100       62 if(ref $item ~~ 'HASH') {
    50          
    0          
135 2         4 push @query, '(';
136 2         8 push @query, $self->parseBranch($item->{left});
137 2         5 push @query, ' ' . $item->{op} . ' ';
138 2         6 push @query, $self->parseBranch($item->{right});
139 2         4 push @query, ')';
140             } elsif(ref $item ~~ 'ARRAY') {
141 14         23 my ($k, $v) = @$item;
142 14         17 push @query, $k;
143 14         17 my $op = '=';
144 14 100       27 if(ref $v eq 'HASH') {
145 6         19 ($op, $v) = %$v;
146             }
147 14         26 push @query, " $op ";
148 14         25 push @query, \$v;
149             } elsif(ref $item) {
150 0         0 push @query, $item;
151             } else {
152 0         0 push @query, $item;
153             }
154 16         95 return @query;
155             }
156              
157             =head2 parseQuery
158              
159             =cut
160              
161             sub parseQuery {
162 0     0 1 0 my $self = shift;
163 0         0 ' Query ';
164             }
165              
166             =head2 quoteIdentifier
167              
168             Convert an identifier to the quoted version.
169              
170             =cut
171              
172             sub quoteIdentifier {
173 7     7 1 9 my $self = shift;
174 7         11 my $k = shift;
175 7         17 return $k;
176 0           return '"'. $k . '"';
177             }
178              
179             1;
180              
181             __END__