File Coverage

blib/lib/SQL/Wizard/Expr.pm
Criterion Covered Total %
statement 67 68 98.5
branch 8 10 80.0
condition 5 9 55.5
subroutine 26 27 96.3
pod 0 8 0.0
total 106 122 86.8


line stmt bran cond sub pod time code
1             package SQL::Wizard::Expr;
2              
3 14     14   4719 use strict;
  14         23  
  14         480  
4 14     14   70 use warnings;
  14         20  
  14         2194  
5 14     14   3180 use Carp;
  14         1677  
  14         4630  
6 14     14   1660 use Scalar::Util qw(blessed);
  14         1630  
  14         5350  
7 14     14   6623 use SQL::Wizard::Expr::Alias;
  14         31  
  14         1969  
8 14     14   4314 use SQL::Wizard::Expr::Order;
  14         32  
  14         348  
9 14     14   4488 use SQL::Wizard::Expr::Window;
  14         30  
  14         370  
10 14     14   4726 use SQL::Wizard::Expr::BinaryOp;
  14         31  
  14         391  
11 14     14   4654 use SQL::Wizard::Expr::Value;
  14         27  
  14         1762  
12              
13             use overload
14 3     3   12 '+' => sub { _binop('+', @_) },
15 1     1   4 '-' => sub { _binop('-', @_) },
16 6     6   17 '*' => sub { _binop('*', @_) },
17 2     2   6 '/' => sub { _binop('/', @_) },
18 1     1   4 '%' => sub { _binop('%', @_) },
19 0     0   0 '""' => sub { croak "Cannot stringify SQL::Wizard::Expr directly; use ->to_sql" },
20 57     57   133 'bool' => sub { 1 },
21 14     14   7235 fallback => 1;
  14         20686  
  14         191  
22              
23             sub new {
24 408     408 0 958 my ($class, %args) = @_;
25 408         2263 bless \%args, $class;
26             }
27              
28             sub to_sql {
29 175     175 0 8412 my ($self, $renderer) = @_;
30 175   33     1540 $renderer ||= $self->{_renderer};
31 175 50       332 croak "No renderer available" unless $renderer;
32 175         541 $renderer->render($self);
33             }
34              
35             sub as {
36 28     28 0 88 my ($self, $alias) = @_;
37 28 50       112 croak "alias must be a word (\\w+), got '$alias'" unless $alias =~ /^\w+$/;
38             SQL::Wizard::Expr::Alias->new(
39             expr => $self,
40             alias => $alias,
41             _renderer => $self->{_renderer},
42 28         353 );
43             }
44              
45             sub asc {
46 2     2 0 6 my ($self) = @_;
47             SQL::Wizard::Expr::Order->new(
48             expr => $self,
49             direction => 'ASC',
50             _renderer => $self->{_renderer},
51 2         56 );
52             }
53              
54             sub desc {
55 2     2 0 5 my ($self) = @_;
56             SQL::Wizard::Expr::Order->new(
57             expr => $self,
58             direction => 'DESC',
59             _renderer => $self->{_renderer},
60 2         12 );
61             }
62              
63             sub asc_nulls_first {
64 1     1 0 3 my ($self) = @_;
65             SQL::Wizard::Expr::Order->new(
66             expr => $self,
67             direction => 'ASC',
68             nulls => 'FIRST',
69             _renderer => $self->{_renderer},
70 1         8 );
71             }
72              
73             sub desc_nulls_last {
74 1     1 0 3 my ($self) = @_;
75             SQL::Wizard::Expr::Order->new(
76             expr => $self,
77             direction => 'DESC',
78             nulls => 'LAST',
79             _renderer => $self->{_renderer},
80 1         8 );
81             }
82              
83             sub over {
84 9     9 0 19 my ($self, @args) = @_;
85             # over('window_name') or over(-partition_by => ..., -order_by => ...)
86 9         10 my $spec;
87 9 100 66     48 if (@args == 1 && !ref $args[0]) {
88 4         9 $spec = { name => $args[0] };
89             } else {
90 5         12 my %opts = @args;
91 5         7 $spec = \%opts;
92             }
93             SQL::Wizard::Expr::Window->new(
94             expr => $self,
95             spec => $spec,
96             _renderer => $self->{_renderer},
97 9         56 );
98             }
99              
100             sub _binop {
101 13     13   27 my ($op, $left, $right, $swap) = @_;
102             # Coerce plain values to Value nodes
103 13         30 $right = _coerce($right, $left);
104 13 100       29 ($left, $right) = ($right, $left) if $swap;
105             SQL::Wizard::Expr::BinaryOp->new(
106             op => $op,
107             left => $left,
108             right => $right,
109             _renderer => $left->{_renderer},
110 13         50 );
111             }
112              
113             sub _coerce {
114 13     13   22 my ($thing, $ref_expr) = @_;
115 13 100 66     79 return $thing if blessed($thing) && $thing->isa('SQL::Wizard::Expr');
116             SQL::Wizard::Expr::Value->new(
117             value => $thing,
118             _renderer => $ref_expr->{_renderer},
119 3         9 );
120             }
121              
122             1;