File Coverage

blib/lib/DBomb/Query/Expr.pm
Criterion Covered Total %
statement 40 85 47.0
branch 8 36 22.2
condition 0 3 0.0
subroutine 10 15 66.6
pod 1 9 11.1
total 59 148 39.8


line stmt bran cond sub pod time code
1             package DBomb::Query::Expr;
2              
3             =head1 NAME
4              
5             DBomb::Query::Expr - Abstraction of a WHERE or ON clause.
6              
7             =head1 SYNOPSIS
8              
9             =cut
10              
11 12     12   77 use strict;
  12         24  
  12         488  
12 12     12   76 use warnings;
  12         22  
  12         565  
13             our $VERSION = '$Revision: 1.11 $';
14              
15 12     12   65 use Carp::Assert;
  12         20  
  12         114  
16 12     12   1858 use DBomb::Util qw(ctx_0 is_same_value);
  12         24  
  12         891  
17             use Class::MethodMaker
18 12         133 'new_with_init' => 'new',
19             'get_set' => [qw(_expr bind_values)],
20 12     12   66 ;
  12         23  
21              
22             ## Export the '_expr()' routine
23 12     12   33028 use base qw(Exporter);
  12         28  
  12         17411  
24             our %EXPORT_TAGS = ('all' => [qw(expr)]);
25             Exporter::export_ok_tags('all');
26              
27             ## new Expr()
28             ## new Expr(+{where_expr}, @bind_values)
29             ## new Expr([where_expr], @bind_values)
30             ## new Expr($plain_sql, @bind_values)
31             sub init
32             {
33 32     32 0 317 my $self = shift;
34 32         924 $self->_expr([]);
35 32         1181 $self->bind_values([]);
36              
37 32 100       1072 return unless @_;
38              
39 1         2 my $e = shift;
40 1 50       5 push @{$self->bind_values}, @_ if @_;
  0         0  
41              
42 1 50       15 if (ref($e) eq 'HASH'){
    50          
    50          
43 0         0 $self->_expr([$e]);
44             }
45             elsif (UNIVERSAL::isa($e,__PACKAGE__)){
46 0         0 $self->append($e);
47             }
48             elsif (not ref($e)) {
49 1         30 $self->_expr([$e]);
50             }
51             else {
52 0         0 $self->_expr($e);
53             }
54             }
55              
56             ## subroutine -- NOT a method.
57             ## Same as new DBomb::Query::Expr(@_)
58             sub expr
59             {
60 0     0 0 0 new DBomb::Query::Expr(@_)
61             }
62              
63             sub append
64             {
65 1     1 0 18 my $self = shift;
66 1         7 return $self->and(@_);
67             }
68              
69             ## and( EXPR, @bind_values)
70             sub and
71             {
72 1     1 1 4 my ($self,$_expr) = (shift,shift);
73 1 50       8 if(not UNIVERSAL::isa($_expr,__PACKAGE__)){
74 0         0 $_expr = $self->new($_expr,@_);
75             }
76 1 50       5 push @{$self->_expr}, ' AND ' if $self->is_not_empty;
  0         0  
77 1         17 push @{$self->_expr}, @{$_expr->_expr};
  1         26  
  1         34  
78 1         12 push @{$self->bind_values}, @{$_expr->bind_values};
  1         30  
  1         43  
79 1         15 return $self;
80             }
81              
82             ## or( EXPR, @bind_values)
83             sub or
84             {
85 0     0 0 0 my ($self,$_expr) = (shift,shift);
86 0 0       0 if(not UNIVERSAL::isa($_expr,__PACKAGE__)){
87 0         0 $_expr = $self->new($_expr,@_);
88             }
89 0 0       0 push @{$self->_expr}, ' OR ' if @{$self->_expr};
  0         0  
  0         0  
90 0         0 push @{$self->_expr}, @{$_expr->_expr};
  0         0  
  0         0  
91 0         0 push @{$self->bind_values}, @{$_expr->bind_values};
  0         0  
  0         0  
92 0         0 return $self;
93             }
94              
95              
96             ## syntax like DBIx::Abstract
97             sub walk_expr
98             {
99 0     0 0 0 my ($self,$e,$dbh) = @_;
100 0 0       0 return 'NULL' if not defined $e;
101 0 0       0 return '?' if $e eq DBomb::Query->PlaceHolder;
102 0 0       0 return $e->walk_expr($e->_expr,$dbh) if UNIVERSAL::isa($e,__PACKAGE__);
103 0 0       0 return $e if not ref $e;
104              
105 0 0       0 if (UNIVERSAL::isa($e,'ARRAY')){
106 0         0 my $sql = join ' ', map { $self->walk_expr($_,$dbh) } @$e;
  0         0  
107 0         0 return "($sql)";
108             }
109              
110 0 0       0 if (ref($e) eq 'HASH'){
111 0 0       0 my $sql = join ' AND ', map {
112             # Promote scalar values to '=' operations.
113 0         0 $e->{$_} = [ '=', $e->{$_}] if not ref $e->{$_};
114              
115 0         0 join(' ', $_, map{$self->walk_expr($_,$dbh)} @{$e->{$_}})
  0         0  
  0         0  
116              
117             } keys %$e;
118 0         0 return $sql;
119             }
120 0         0 die "Unrecognized expression $e";
121             }
122              
123             sub sql
124             {
125 0     0 0 0 my ($self,$dbh) = @_;
126 0 0 0     0 return ctx_0('') unless defined($self->_expr) && @{$self->_expr};
  0         0  
127 0 0       0 return ctx_0($self->_expr,@{$self->bind_values}) if not ref $self->_expr; ## plain sql... actually, the ctor should have ruled this out.
  0         0  
128              
129 0         0 return ctx_0($self->walk_expr($self->_expr,$dbh), @{$self->bind_values});
  0         0  
130             }
131              
132 1     1 0 1 sub is_not_empty { scalar @{shift->_expr} }
  1         29  
133 0     0 0   sub is_empty { not shift->is_not_empty }
134              
135              
136             1;
137             __END__