File Coverage

blib/lib/SQL/Wizard/Expr/Select.pm
Criterion Covered Total %
statement 70 71 98.5
branch 25 30 83.3
condition n/a
subroutine 18 18 100.0
pod 0 13 0.0
total 113 132 85.6


line stmt bran cond sub pod time code
1             package SQL::Wizard::Expr::Select;
2              
3 14     14   67 use strict;
  14         23  
  14         413  
4 14     14   49 use warnings;
  14         21  
  14         521  
5 14     14   6985 use Storable qw(dclone);
  14         48772  
  14         1013  
6 14     14   83 use parent 'SQL::Wizard::Expr';
  14         18  
  14         82  
7 14     14   6717 use SQL::Wizard::Expr::Compound;
  14         42  
  14         8827  
8              
9             sub new {
10 131     131 0 297 my ($class, %args) = @_;
11 131         501 $class->SUPER::new(%args);
12             }
13              
14             # Build a Select node from the standard -key => value API args.
15             # Accepts extra key/value pairs (e.g. _cte, _renderer) merged in.
16             sub from_args {
17 131     131 0 355 my ($class, %args) = @_;
18 131 50       342 Carp::confess("select requires -from") unless $args{'-from'};
19 131         172 my %node;
20 131 100       310 $node{distinct} = $args{'-distinct'} if $args{'-distinct'};
21 131 100       324 $node{columns} = $args{'-columns'} if $args{'-columns'};
22 131 50       322 $node{from} = $args{'-from'} if $args{'-from'};
23 131 100       378 $node{where} = $args{'-where'} if $args{'-where'};
24 131 100       254 $node{group_by} = $args{'-group_by'} if $args{'-group_by'};
25 131 100       280 $node{having} = $args{'-having'} if $args{'-having'};
26 131 100       262 $node{order_by} = $args{'-order_by'} if $args{'-order_by'};
27 131 100       253 $node{limit} = $args{'-limit'} if defined $args{'-limit'};
28 131 100       268 $node{offset} = $args{'-offset'} if defined $args{'-offset'};
29 131 100       218 $node{window} = $args{'-window'} if $args{'-window'};
30 131 100       230 $node{_cte} = $args{_cte} if $args{_cte};
31 131 50       304 $node{_renderer} = $args{_renderer} if $args{_renderer};
32 131         419 $class->new(%node);
33             }
34              
35             # Immutable modifiers — return cloned objects
36              
37             sub distinct {
38 1     1 0 7 my ($self) = @_;
39 1         162 my $clone = dclone($self);
40 1         4 $clone->{distinct} = 1;
41 1         6 return $clone;
42             }
43              
44             sub where {
45 2     2 0 2247 my ($self, $where) = @_;
46 2         237 my $clone = dclone($self);
47 2         7 $clone->{where} = $where;
48 2         4 return $clone;
49             }
50              
51             sub add_where {
52 2     2 0 1632 my ($self, $extra) = @_;
53 2         103 my $clone = dclone($self);
54 2 50       8 if ($clone->{where}) {
55 2         5 $clone->{where} = [-and => $clone->{where}, $extra];
56             } else {
57 0         0 $clone->{where} = $extra;
58             }
59 2         5 return $clone;
60             }
61              
62             sub columns {
63 1     1 0 2 my ($self, $cols) = @_;
64 1         75 my $clone = dclone($self);
65 1         3 $clone->{columns} = $cols;
66 1         3 return $clone;
67             }
68              
69             sub order_by {
70 2     2 0 1069 my ($self, @order) = @_;
71 2         110 my $clone = dclone($self);
72 2 50       9 $clone->{order_by} = @order == 1 ? $order[0] : \@order;
73 2         5 return $clone;
74             }
75              
76             sub limit {
77 3     3 0 1850 my ($self, $limit) = @_;
78 3         111 my $clone = dclone($self);
79 3         7 $clone->{limit} = $limit;
80 3         8 return $clone;
81             }
82              
83             sub offset {
84 2     2 0 3 my ($self, $offset) = @_;
85 2         59 my $clone = dclone($self);
86 2         4 $clone->{offset} = $offset;
87 2         4 return $clone;
88             }
89              
90             # Compound query methods
91              
92             sub union {
93 5     5 0 24 my ($self, $other) = @_;
94             SQL::Wizard::Expr::Compound->new(
95             queries => [{ type => undef, query => $self }, { type => 'UNION', query => $other }],
96             _renderer => $self->{_renderer},
97 5         66 );
98             }
99              
100             sub union_all {
101 1     1 0 5 my ($self, $other) = @_;
102             SQL::Wizard::Expr::Compound->new(
103             queries => [{ type => undef, query => $self }, { type => 'UNION ALL', query => $other }],
104             _renderer => $self->{_renderer},
105 1         7 );
106             }
107              
108             sub intersect {
109 1     1 0 6 my ($self, $other) = @_;
110             SQL::Wizard::Expr::Compound->new(
111             queries => [{ type => undef, query => $self }, { type => 'INTERSECT', query => $other }],
112             _renderer => $self->{_renderer},
113 1         6 );
114             }
115              
116             sub except {
117 1     1 0 5 my ($self, $other) = @_;
118             SQL::Wizard::Expr::Compound->new(
119             queries => [{ type => undef, query => $self }, { type => 'EXCEPT', query => $other }],
120             _renderer => $self->{_renderer},
121 1         14 );
122             }
123              
124             1;