File Coverage

blib/lib/SQL/Functional.pm
Criterion Covered Total %
statement 6 8 75.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 9 11 81.8


line stmt bran cond sub pod time code
1             # Copyright (c) 2016 Timm Murray
2             # All rights reserved.
3             #
4             # Redistribution and use in source and binary forms, with or without
5             # modification, are permitted provided that the following conditions are met:
6             #
7             # * Redistributions of source code must retain the above copyright notice,
8             # this list of conditions and the following disclaimer.
9             # * Redistributions in binary form must reproduce the above copyright
10             # notice, this list of conditions and the following disclaimer in the
11             # documentation and/or other materials provided with the distribution.
12             #
13             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23             # POSSIBILITY OF SUCH DAMAGE.
24             package SQL::Functional;
25             $SQL::Functional::VERSION = '0.1';
26 23     23   313253 use v5.14;
  23         61  
27 23     23   75 use warnings;
  23         22  
  23         519  
28 23     23   7544 use SQL::Functional::AndClause;
  0            
  0            
29             use SQL::Functional::DeleteClause;
30             use SQL::Functional::FromClause;
31             use SQL::Functional::GroupByClause;
32             use SQL::Functional::InnerJoinClause;
33             use SQL::Functional::InsertClause;
34             use SQL::Functional::MatchClause;
35             use SQL::Functional::NullClause;
36             use SQL::Functional::OrClause;
37             use SQL::Functional::OrderByClause;
38             use SQL::Functional::PlaceholderClause;
39             use SQL::Functional::SelectClause;
40             use SQL::Functional::SetClause;
41             use SQL::Functional::TableClause;
42             use SQL::Functional::UpdateClause;
43             use SQL::Functional::ValuesClause;
44             use SQL::Functional::VerbatimClause;
45             use SQL::Functional::WhereClause;
46             use SQL::Functional::WrapClause;
47             use Exporter;
48             our @ISA = qw{ Exporter };
49              
50             our @EXPORT_OK = qw{
51             SELECT
52             star
53             field
54             col
55             FROM
56             WHERE
57             match
58             match_verbatim
59             op
60             table
61             ORDER_BY
62             DESC
63             INNER_JOIN
64             SUBSELECT
65             AND
66             OR
67             INSERT
68             INTO
69             VALUES
70             UPDATE
71             SET
72             DELETE
73             wrap
74             IS_NULL
75             IS_NOT_NULL
76             GROUP_BY
77             };
78             our @EXPORT = @EXPORT_OK;
79              
80             # ABSTRACT: Create SQL programmatically
81              
82              
83             sub SELECT ($$@)
84             {
85             my ($fields, @clauses) = @_;
86             my @fields;
87             if( ref $fields eq 'ARRAY' ) {
88             @fields = map {
89             (ref($_) && $_->isa( 'SQL::Functional::FieldClause' ))
90             ? $_
91             : SQL::Functional::FieldClause->new({
92             name => $_,
93             });
94             } @$fields;
95             }
96             elsif( $fields->isa( 'SQL::Functional::FieldClause' ) ) {
97             @fields = ($fields);
98             }
99             else {
100             @fields = ( SQL::Functional::FieldClause->new({
101             name => $fields,
102             }) );
103             }
104              
105             my $clause = SQL::Functional::SelectClause->new(
106             fields => \@fields,
107             clauses => \@clauses,
108             );
109             return ($clause->to_string, $clause->get_params);
110             }
111              
112             sub star ()
113             {
114             return field( '*' );
115             }
116              
117             sub field ($)
118             {
119             my ($name) = @_;
120             return SQL::Functional::FieldClause->new({
121             name => $name,
122             });
123             }
124             *col = \&field;
125              
126             sub table($)
127             {
128             my ($name) = @_;
129             my $table = SQL::Functional::TableClause->new({
130             name => $name,
131             });
132             return $table;
133             }
134             *INTO = \&table;
135              
136             sub FROM (@)
137             {
138             my (@tables) = @_;
139             my @table_objs = map {
140             ref $_ ? $_ : table $_
141             } @tables;
142              
143             my $clause = SQL::Functional::FromClause->new({
144             tables => \@table_objs
145             });
146              
147             return $clause;
148             }
149              
150             sub WHERE ($)
151             {
152             my ($clause) = @_;
153             my @params = $clause->params;
154              
155             my $where = SQL::Functional::WhereClause->new({
156             params => \@params,
157             sub_clause => $clause,
158             });
159             return $where;
160             }
161              
162             sub match($$$)
163             {
164             my ($field, $op, $value) = @_;
165              
166             my $field_obj = ref($field)
167             ? $field
168             : SQL::Functional::FieldClause->new({
169             name => $field,
170             });
171             my $clause_value =
172             ref($value) && $value->does( 'SQL::Functional::Clause' )
173             ? $value
174             : SQL::Functional::PlaceholderClause->new({
175             value => $value,
176             });
177             my $clause = SQL::Functional::MatchClause->new({
178             field => $field_obj,
179             op => $op,
180             value => $clause_value,
181             });
182             return $clause;
183             }
184             *op = \&match;
185              
186             sub match_verbatim($$$)
187             {
188             my ($field, $op, $value) = @_;
189              
190             my $field_obj = ref($field)
191             ? $field
192             : SQL::Functional::FieldClause->new({
193             name => $field,
194             });
195             my $clause_value =
196             ref($value) && $value->does( 'SQL::Functional::Clause' )
197             ? $value
198             : SQL::Functional::VerbatimClause->new({
199             value => $value,
200             });
201              
202             my $clause = SQL::Functional::MatchClause->new({
203             field => $field_obj,
204             op => $op,
205             value => $clause_value,
206             });
207             return $clause;
208             }
209              
210             sub ORDER_BY($;@)
211             {
212             my (@fields) = @_;
213             my $clause = SQL::Functional::OrderByClause->new({
214             fields => \@fields,
215             });
216             return $clause;
217             }
218              
219             sub DESC($)
220             {
221             my ($field) = @_;
222             # TODO should this be an object? It'd be consistent with everything
223             # else to make it one. Is there an argument besides consistency?
224             # Seems just fine like this so far . . .
225             return "$field DESC";
226             }
227              
228             sub INNER_JOIN($$$)
229             {
230             my ($table, $field1, $field2) = @_;
231             my $clause = SQL::Functional::InnerJoinClause->new(
232             table => $table,
233             field1 => $field1,
234             field2 => $field2,
235             );
236             return $clause;
237             }
238              
239             sub SUBSELECT($$@)
240             {
241             my ($fields, @clauses) = @_;
242             my @fields;
243             if( ref $fields eq 'ARRAY' ) {
244             @fields = map {
245             (ref($_) && $_->isa( 'SQL::Functional::FieldClause' ))
246             ? $_
247             : SQL::Functional::FieldClause->new({
248             name => $_,
249             });
250             } @$fields;
251             }
252             elsif( $fields->isa( 'SQL::Functional::FieldClause' ) ) {
253             @fields = ($fields);
254             }
255             else {
256             @fields = ( SQL::Functional::FieldClause->new({
257             name => $fields,
258             }) );
259             }
260              
261             my $clause = SQL::Functional::SelectClause->new({
262             fields => \@fields,
263             clauses => \@clauses,
264             });
265             return $clause;
266             }
267              
268             sub AND
269             {
270             my (@clauses) = @_;
271             my $clause = SQL::Functional::AndClause->new({
272             clauses => \@clauses,
273             });
274             return $clause;
275             }
276              
277             sub OR
278             {
279             my (@clauses) = @_;
280             my $clause = SQL::Functional::OrClause->new({
281             clauses => \@clauses,
282             });
283             return $clause;
284             }
285              
286             sub INSERT ($$$)
287             {
288             my ($into, $fields, $values) = @_;
289             my $clause = SQL::Functional::InsertClause->new(
290             into => $into,
291             fields => ref $fields ? $fields : [$fields],
292             values => $values,
293             );
294             return ($clause->to_string, $clause->get_params);
295             }
296              
297             sub VALUES ($)
298             {
299             my ($values) = @_;
300             my $clause = SQL::Functional::ValuesClause->new(
301             params => $values,
302             );
303             return $clause;
304             }
305              
306             sub UPDATE ($$;$)
307             {
308             my ($table, $set, $where) = @_;
309             my $clause = SQL::Functional::UpdateClause->new(
310             table => $table,
311             set => $set,
312             where => $where,
313             );
314             return ($clause->to_string, $clause->get_params);
315             }
316              
317             sub SET
318             {
319             my (@clauses) = @_;
320             my $clause = SQL::Functional::SetClause->new(
321             clauses => \@clauses,
322             );
323             return $clause;
324             }
325              
326             sub DELETE ($;$)
327             {
328             my ($from, $where) = @_;
329             my $clause = SQL::Functional::DeleteClause->new(
330             from => $from,
331             where => $where,
332             );
333             return ($clause->to_string, $clause->get_params);
334             }
335              
336             sub wrap ($)
337             {
338             my ($clause) = @_;
339             my $wrap = SQL::Functional::WrapClause->new({
340             clause => $clause,
341             });
342             return $wrap;
343             }
344              
345             sub IS_NULL ($)
346             {
347             my ($field) = @_;
348             my $field_clause = ref $field
349             ? $field
350             : SQL::Functional::FieldClause->new({
351             name => $field,
352             });
353              
354             my $clause = SQL::Functional::NullClause->new({
355             field => $field_clause,
356             });
357             return $clause;
358             }
359              
360             sub IS_NOT_NULL ($)
361             {
362             my ($field) = @_;
363             my $field_clause = ref $field
364             ? $field
365             : SQL::Functional::FieldClause->new({
366             name => $field,
367             });
368              
369             my $clause = SQL::Functional::NullClause->new(
370             field => $field_clause,
371             not => 1,
372             );
373             return $clause;
374             }
375              
376             sub GROUP_BY ($)
377             {
378             my ($field) = @_;
379             my $field_clause = ref $field
380             ? $field
381             : SQL::Functional::FieldClause->new({
382             name => $field,
383             });
384              
385             my $clause = SQL::Functional::GroupByClause->new({
386             field => $field_clause,
387             });
388             return $clause;
389             }
390              
391              
392             1;
393             __END__