File Coverage

blib/lib/Class/ReluctantORM/SQL/Param.pm
Criterion Covered Total %
statement 21 69 30.4
branch 0 24 0.0
condition 0 8 0.0
subroutine 7 16 43.7
pod 8 8 100.0
total 36 125 28.8


line stmt bran cond sub pod time code
1             package Class::ReluctantORM::SQL::Param;
2              
3             =head1 NAME
4              
5             Class::ReluctantORM::SQL::Param - Represent a placeholder in a SQL statement
6              
7             =head1 SYNOPSIS
8              
9             use Class::ReluctantORM::SQL::Aliases;
10              
11             # Make a placeholder
12             my $param = Param->new();
13              
14             # Set and read a value to the param
15             $param->bind_value('foo');
16             $param->bind_value(undef); # This binds NULL
17             my $val = $param->bind_value();
18              
19             # Use the param in a Where criterion ('foo = ?')
20             my $crit = Criterion->new('=', Column->new(column => 'foo'), $p);
21              
22              
23             =head1 DESCRIPTION
24              
25             Represents a placeholder in a SQL statement.
26              
27             =cut
28              
29 1     1   5 use strict;
  1         2  
  1         33  
30 1     1   7 use warnings;
  1         2  
  1         24  
31              
32 1     1   19 use Data::Dumper;
  1         3  
  1         52  
33 1     1   6 use Class::ReluctantORM::Exception;
  1         2  
  1         28  
34 1     1   5 use Class::ReluctantORM::Utilities qw(install_method);
  1         3  
  1         45  
35 1     1   5 use Scalar::Util qw(looks_like_number);
  1         2  
  1         48  
36              
37 1     1   6 use base 'Class::ReluctantORM::SQL::Expression';
  1         2  
  1         718  
38             our $DEBUG = 0;
39              
40             =head1 CONSTRUCTOR
41              
42             =cut
43              
44             =head2 $p = Param->new();
45              
46             =head2 $p = Param->new($value);
47              
48             =head2 $p = Param->new(undef);
49              
50             Makes a new param object.
51              
52             In the first form, no value is bound.
53              
54             In the second form, the given value is bound.
55              
56             In the third form, the NULL value is bound.
57              
58             =cut
59              
60             sub new {
61 0     0 1   my $class = shift;
62 0           my $self = bless {}, $class;
63              
64 0 0         if (@_) {
65 0           $self->bind_value(@_);
66             }
67              
68 0           return $self;
69             }
70              
71              
72              
73             =head1 ACCESSORS and MUTATORS
74              
75             =cut
76              
77             =head2 $v = $p->bind_value();
78              
79             =head2 $p->bind_value($value);
80              
81             =head2 $p->bind_value(undef);
82              
83             Reads or sets the value used in Driver parameter binding.
84              
85             In the first form, the value, if any, is returned. An undefined value is ambiguous;
86             use has_bind_Value to detect a bind value.
87              
88             In the second form, the bind value is set to the scalar provided.
89              
90             In the third form, the bind value is set to undef, which means it will be interpreted by the Driver as NULL.
91              
92             =cut
93              
94             sub bind_value {
95 0     0 1   my $self = shift;
96 0 0         if (@_) {
97 0           $self->has_bind_value(1);
98 0           my $value = shift;
99 0 0 0       unless (!defined($value) || !ref($value)) {
100 0           Class::ReluctantORM::Exception::Param::WrongType->croak(
101             error => 'bind_Value must be a either a scalar or undef',
102             expected => 'scalar',
103             value => $value,
104             );
105             }
106 0 0         if (@_) {
107 0           Class::ReluctantORM::Exception::Param::Spurious->croak();
108             }
109 0           $self->set('bind_value', $value);
110             }
111 0           return $self->get('bind_value');
112             }
113              
114              
115             =head2 @empty = $p->child_expressions();
116              
117             Always returns an empty list. Required by the Expression interface.
118              
119             =cut
120              
121 0     0 1   sub child_expressions { return (); }
122              
123             =head2 $bool = $p->has_bind_value()
124              
125             If true a bind value has been set. Don't
126             rely on bind_value(), as undef is a valid value.
127              
128             =cut
129              
130             __PACKAGE__->mk_accessors(qw(has_bind_value));
131              
132             =head2 $bool = $arg->is_param();
133              
134             All objects of this class return true. The class add this method to its parent class, making all other subclasses of return false.
135              
136             =cut
137              
138 0     0     install_method('Class::ReluctantORM::SQL::Expression', 'is_param', sub { return 0; });
139 0     0 1   sub is_param { return 1; }
140              
141              
142             =head2 $bool = $p->is_leaf_expression();
143              
144             Always returns true for this class. Required by the Expression interface.
145              
146             =cut
147              
148 0     0 1   sub is_leaf_expression { return 1; }
149              
150             =head2 $str = $param->pretty_print();
151              
152             Renders a human-readable representation of the Param.
153              
154             =cut
155              
156             sub pretty_print {
157 0     0 1   my $self = shift;
158 0           my %args = @_;
159 0 0         if ($args{one_line}) {
160 0           my $str = '?';
161 0 0         if ($self->has_bind_value) {
162 0           $str .= '(bind:';
163 0           my $val = $self->bind_value();
164 0 0         if (!defined($val)) {
    0          
165 0           $str .= 'NULL';
166             } elsif (looks_like_number($val)) {
167 0           $str .= $val;
168             } else {
169 0           $str .= "'" . $val . "'";
170             }
171 0           $str .= ')';
172             }
173 0           return $str;
174             } else {
175 0   0       return ($args{prefix} || '' ) . 'PARAM ' . $self->pretty_print(one_line => 1) . "\n";
176             }
177             }
178              
179             =head2 $clone = $p->clone();
180              
181             Creates a new Param, copying the bound value of the original if it had one.
182              
183             =cut
184              
185             sub clone {
186 0     0 1   my $self = shift;
187 0           my $class = ref $self;
188 0 0         if ($self->has_bind_value) {
189 0           return $class->new($self->bind_value());
190             } else {
191 0           return $class->new();
192             }
193             }
194              
195             =head2 $bool = $param->is_equivalent($expr);
196              
197             Returns true if $expr is a Param, with matching has_bind_value() and value.
198              
199             =cut
200              
201             sub is_equivalent {
202 0     0 1   my $left = shift;
203 0           my $right = shift;
204 0 0         unless ($right->is_param()) { return 0; }
  0            
205              
206 0 0         if ($left->has_bind_value()) {
207 0 0         unless ($right->has_bind_value()) { return 0; }
  0            
208 0           my ($lbv, $rbv) = ($left->bind_value(), $right->bind_value());
209             return (
210 0   0       (!defined($lbv) && !defined($rbv)) # both undef
211             ||
212             ((defined($lbv) && defined($rbv)) && ($lbv == $rbv)) # both defined and equal
213             );
214             } else {
215 0           return !$right->has_bind_value();
216             }
217             }
218              
219              
220             =head1 AUTHOR
221              
222             Clinton Wolfe
223              
224             =cut
225              
226             1;