File Coverage

blib/lib/Fey/Literal/Term.pm
Criterion Covered Total %
statement 33 33 100.0
branch 4 4 100.0
condition 3 3 100.0
subroutine 11 11 100.0
pod 2 2 100.0
total 53 53 100.0


line stmt bran cond sub pod time code
1             package Fey::Literal::Term;
2              
3 28     28   138 use strict;
  28         67  
  28         1117  
4 28     28   127 use warnings;
  28         41  
  28         843  
5 28     28   126 use namespace::autoclean;
  28         39  
  28         217  
6              
7             our $VERSION = '0.42';
8              
9 28     28   2567 use Fey::Types qw( Bool LiteralTermArg );
  28         47  
  28         212  
10              
11 28     28   299861 use Carp qw( croak );
  28         56  
  28         1883  
12 28     28   128 use Moose 0.90;
  28         726  
  28         212  
13 28     28   151126 use MooseX::SemiAffordanceAccessor 0.03;
  28         762  
  28         177  
14 28     28   80288 use MooseX::StrictConstructor 0.07;
  28         623  
  28         176  
15              
16             with 'Fey::Role::Comparable', 'Fey::Role::Selectable',
17             'Fey::Role::Orderable', 'Fey::Role::Groupable',
18             'Fey::Role::IsLiteral';
19              
20             has 'term' => (
21             is => 'ro',
22             isa => LiteralTermArg,
23             required => 1,
24             coerce => 1,
25             );
26              
27             has can_have_alias => (
28             is => 'rw',
29             isa => Bool,
30             default => 1,
31             );
32              
33             with 'Fey::Role::HasAliasName' => { generated_alias_prefix => 'TERM' };
34              
35             sub BUILDARGS {
36 13     13 1 29 my $class = shift;
37              
38 13         461 return { term => [@_] };
39             }
40              
41             sub sql {
42 19     19 1 782 my ( $self, $dbh ) = @_;
43              
44 24 100 100     538 return join(
45             '',
46             map {
47 19         677 blessed($_) && $_->can('sql_or_alias')
48             ? $_->sql_or_alias($dbh)
49             : $_
50 19         30 } @{ $self->term() }
51             );
52             }
53              
54             # XXX - this bit of wackness is necessary because MX::Role::Parameterized
55             # doesn't support -alias or -excludes, but we want to provide our own version
56             # of sql_with_alias.
57             {
58             my $meta = __PACKAGE__->meta();
59              
60             my $method = $meta->remove_method('sql_with_alias');
61             $meta->add_method( _han_sql_with_alias => $method );
62              
63             my $sql_with_alias = sub {
64 3     3   12 my $self = shift;
65 3         7 my $dbh = shift;
66              
67 3 100       151 return $self->can_have_alias()
68             ? $self->_han_sql_with_alias($dbh)
69             : $self->sql($dbh);
70             };
71              
72             $meta->add_method( sql_with_alias => $sql_with_alias );
73             }
74              
75             before 'set_alias_name' => sub {
76             my $self = shift;
77              
78             croak 'This term cannot have an alias'
79             unless $self->can_have_alias();
80             };
81              
82             __PACKAGE__->meta()->make_immutable();
83              
84             1;
85              
86             # ABSTRACT: Represents a literal term in a SQL statement
87              
88             __END__
89              
90             =pod
91              
92             =head1 NAME
93              
94             Fey::Literal::Term - Represents a literal term in a SQL statement
95              
96             =head1 VERSION
97              
98             version 0.42
99              
100             =head1 SYNOPSIS
101              
102             my $term = Fey::Literal::Term->new(@anything)
103              
104             =head1 DESCRIPTION
105              
106             This class represents a literal term in a SQL statement. A "term" in this
107             module means a literal SQL snippet that will be used verbatim, without
108             quoting.
109              
110             This allows you to create SQL for almost any expression, for example
111             C<EXTRACT( DOY FROM TIMESTAMP "User.creation_date" )>, which is a valid Postgres
112             expression. This would be created like this:
113              
114             my $term =
115             Fey::Literal::Term->new
116             ( 'DOY FROM TIMESTAMP ', $column );
117              
118             my $function = Fey::Literal::Function->new( 'EXTRACT', $term );
119              
120             This ability to insert arbitrary strings into a SQL statement is meant
121             to be used as a back-door to support any sort of SQL snippet not
122             otherwise supported by the core Fey classes in a more direct manner.
123              
124             =head1 INHERITANCE
125              
126             This module is a subclass of C<Fey::Literal>.
127              
128             =head1 METHODS
129              
130             This class provides the following methods:
131              
132             =head2 Fey::Literal::Term->new(@fragments)
133              
134             This method creates a new C<Fey::Literal::Term> object representing
135             the term passed to the constructor.
136              
137             More than one argument may be given; they will all be joined together
138             in the generated SQL. For example:
139              
140             my $term = Fey::Literal::Term->new( $column, '::text' );
141              
142             The arguments can be plain scalars, objects with a C<sql_or_alias()>
143             method (columns, tables, etc.) or any object which is overloaded (the
144             assumption being it that it overloads stringification).
145              
146             =head2 $term->term()
147              
148             Returns the array reference of fragments passed to the constructor.
149              
150             =head2 $term->can_have_alias()
151              
152             =head2 $term->set_can_have_alias()
153              
154             If this attribute is explicitly set to a false value, then then the
155             SQL-generating methods below will never include an alias.
156              
157             =head2 $term->id()
158              
159             The id for a term is uniquely identifies the term.
160              
161             =head2 $term->sql()
162              
163             =head2 $term->sql_with_alias()
164              
165             =head2 $term->sql_or_alias()
166              
167             Returns the appropriate SQL snippet. If the term contains any Fey objects,
168             their C<sql_or_alias()> method is called to generate their part of the term.
169              
170             =head1 DETAILS OF SQL GENERATION
171              
172             A term generates SQL by taking each of the elements passed to its constructor
173             and concatenating them. If the element is an object with a C<sql_or_alias()>
174             method, that method will be called to generate SQL. Otherwise, the element is
175             just used as-is.
176              
177             If C<< $term->can_have_alias() >> is false, then calling any of the three
178             SQL-generating methods is always equivalent to calling C<< $term->sql() >>.
179              
180             =head1 ROLES
181              
182             This class does the C<Fey::Role::Selectable>, C<Fey::Role::Comparable>,
183             C<Fey::Role::Groupable>, and C<Fey::Role::Orderable> roles.
184              
185             Of course, the contents of a given term may not really allow for any
186             of these things, but having this class do these roles means you can
187             freely use a term object in any part of a SQL snippet.
188              
189             =head1 BUGS
190              
191             See L<Fey> for details on how to report bugs.
192              
193             =head1 AUTHOR
194              
195             Dave Rolsky <autarch@urth.org>
196              
197             =head1 COPYRIGHT AND LICENSE
198              
199             This software is Copyright (c) 2011 - 2015 by Dave Rolsky.
200              
201             This is free software, licensed under:
202              
203             The Artistic License 2.0 (GPL Compatible)
204              
205             =cut