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   6294 use strict;
  14         28  
  14         620  
4 14     14   132 use warnings;
  14         43  
  14         647  
5 14     14   3605 use Carp;
  14         3970  
  14         3550  
6 14     14   2286 use Scalar::Util qw(blessed);
  14         64  
  14         10448  
7 14     14   11953 use SQL::Wizard::Expr::Alias;
  14         40  
  14         557  
8 14     14   5804 use SQL::Wizard::Expr::Order;
  14         40  
  14         544  
9 14     14   5408 use SQL::Wizard::Expr::Window;
  14         38  
  14         509  
10 14     14   5743 use SQL::Wizard::Expr::BinaryOp;
  14         37  
  14         455  
11 14     14   5912 use SQL::Wizard::Expr::Value;
  14         37  
  14         2631  
12              
13             use overload
14 3     3   20 '+' => sub { _binop('+', @_) },
15 1     1   5 '-' => sub { _binop('-', @_) },
16 6     6   22 '*' => sub { _binop('*', @_) },
17 2     2   8 '/' => sub { _binop('/', @_) },
18 1     1   6 '%' => sub { _binop('%', @_) },
19 0     0   0 '""' => sub { croak "Cannot stringify SQL::Wizard::Expr directly; use ->to_sql" },
20 57     57   143 'bool' => sub { 1 },
21 14     14   9027 fallback => 1;
  14         25869  
  14         198  
22              
23             sub new {
24 384     384 0 1121 my ($class, %args) = @_;
25 384         2729 bless \%args, $class;
26             }
27              
28             sub to_sql {
29 171     171 0 6134 my ($self, $renderer) = @_;
30 171   33     1877 $renderer ||= $self->{_renderer};
31 171 50       402 croak "No renderer available" unless $renderer;
32 171         737 $renderer->render($self);
33             }
34              
35             sub as {
36 28     28 0 104 my ($self, $alias) = @_;
37 28 50       217 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         502 );
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         62 );
52             }
53              
54             sub desc {
55 2     2 0 6 my ($self) = @_;
56             SQL::Wizard::Expr::Order->new(
57             expr => $self,
58             direction => 'DESC',
59             _renderer => $self->{_renderer},
60 2         10 );
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         4 );
71             }
72              
73             sub desc_nulls_last {
74 1     1 0 2 my ($self) = @_;
75             SQL::Wizard::Expr::Order->new(
76             expr => $self,
77             direction => 'DESC',
78             nulls => 'LAST',
79             _renderer => $self->{_renderer},
80 1         6 );
81             }
82              
83             sub over {
84 9     9 0 28 my ($self, @args) = @_;
85             # over('window_name') or over(-partition_by => ..., -order_by => ...)
86 9         18 my $spec;
87 9 100 66     46 if (@args == 1 && !ref $args[0]) {
88 4         13 $spec = { name => $args[0] };
89             } else {
90 5         17 my %opts = @args;
91 5         11 $spec = \%opts;
92             }
93             SQL::Wizard::Expr::Window->new(
94             expr => $self,
95             spec => $spec,
96             _renderer => $self->{_renderer},
97 9         99 );
98             }
99              
100             sub _binop {
101 13     13   38 my ($op, $left, $right, $swap) = @_;
102             # Coerce plain values to Value nodes
103 13         32 $right = _coerce($right, $left);
104 13 100       39 ($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         65 );
111             }
112              
113             sub _coerce {
114 13     13   28 my ($thing, $ref_expr) = @_;
115 13 100 66     133 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         14 );
120             }
121              
122             1;