| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package SQL::Wizard; |
|
2
|
|
|
|
|
|
|
|
|
3
|
14
|
|
|
14
|
|
1382761
|
use strict; |
|
|
14
|
|
|
|
|
25
|
|
|
|
14
|
|
|
|
|
500
|
|
|
4
|
14
|
|
|
14
|
|
124
|
use warnings; |
|
|
14
|
|
|
|
|
25
|
|
|
|
14
|
|
|
|
|
691
|
|
|
5
|
14
|
|
|
14
|
|
66
|
use Carp; |
|
|
14
|
|
|
|
|
19
|
|
|
|
14
|
|
|
|
|
1024
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.09'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
14
|
|
|
14
|
|
7212
|
use SQL::Wizard::Renderer; |
|
|
14
|
|
|
|
|
47
|
|
|
|
14
|
|
|
|
|
729
|
|
|
10
|
14
|
|
|
14
|
|
6095
|
use SQL::Wizard::Expr::Column; |
|
|
14
|
|
|
|
|
35
|
|
|
|
14
|
|
|
|
|
480
|
|
|
11
|
14
|
|
|
14
|
|
79
|
use SQL::Wizard::Expr::Value; |
|
|
14
|
|
|
|
|
20
|
|
|
|
14
|
|
|
|
|
238
|
|
|
12
|
14
|
|
|
14
|
|
4896
|
use SQL::Wizard::Expr::Raw; |
|
|
14
|
|
|
|
|
60
|
|
|
|
14
|
|
|
|
|
382
|
|
|
13
|
14
|
|
|
14
|
|
5214
|
use SQL::Wizard::Expr::Func; |
|
|
14
|
|
|
|
|
37
|
|
|
|
14
|
|
|
|
|
388
|
|
|
14
|
14
|
|
|
14
|
|
5781
|
use SQL::Wizard::Expr::Case; |
|
|
14
|
|
|
|
|
35
|
|
|
|
14
|
|
|
|
|
390
|
|
|
15
|
14
|
|
|
14
|
|
5425
|
use SQL::Wizard::Expr::Join; |
|
|
14
|
|
|
|
|
33
|
|
|
|
14
|
|
|
|
|
390
|
|
|
16
|
14
|
|
|
14
|
|
5686
|
use SQL::Wizard::Expr::Select; |
|
|
14
|
|
|
|
|
41
|
|
|
|
14
|
|
|
|
|
461
|
|
|
17
|
14
|
|
|
14
|
|
5434
|
use SQL::Wizard::Expr::Insert; |
|
|
14
|
|
|
|
|
41
|
|
|
|
14
|
|
|
|
|
533
|
|
|
18
|
14
|
|
|
14
|
|
5126
|
use SQL::Wizard::Expr::Update; |
|
|
14
|
|
|
|
|
35
|
|
|
|
14
|
|
|
|
|
386
|
|
|
19
|
14
|
|
|
14
|
|
5526
|
use SQL::Wizard::Expr::Delete; |
|
|
14
|
|
|
|
|
46
|
|
|
|
14
|
|
|
|
|
420
|
|
|
20
|
14
|
|
|
14
|
|
5189
|
use SQL::Wizard::Expr::CTE; |
|
|
14
|
|
|
|
|
40
|
|
|
|
14
|
|
|
|
|
35634
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub new { |
|
23
|
14
|
|
|
14
|
1
|
2088091
|
my ($class, %args) = @_; |
|
24
|
|
|
|
|
|
|
my $self = bless { |
|
25
|
|
|
|
|
|
|
dialect => $args{dialect} || 'ansi', |
|
26
|
14
|
|
50
|
|
|
255
|
renderer => SQL::Wizard::Renderer->new(dialect => $args{dialect} || 'ansi'), |
|
|
|
|
50
|
|
|
|
|
|
27
|
|
|
|
|
|
|
}, $class; |
|
28
|
14
|
|
|
|
|
63
|
$self; |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
## Expression primitives |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub col { |
|
34
|
42
|
|
|
42
|
1
|
20724
|
my ($self, $name) = @_; |
|
35
|
|
|
|
|
|
|
SQL::Wizard::Expr::Column->new( |
|
36
|
|
|
|
|
|
|
name => $name, |
|
37
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
38
|
42
|
|
|
|
|
220
|
); |
|
39
|
|
|
|
|
|
|
} |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub val { |
|
42
|
29
|
|
|
29
|
1
|
8071
|
my ($self, $value) = @_; |
|
43
|
|
|
|
|
|
|
SQL::Wizard::Expr::Value->new( |
|
44
|
|
|
|
|
|
|
value => $value, |
|
45
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
46
|
29
|
|
|
|
|
123
|
); |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub raw { |
|
50
|
5
|
|
|
5
|
1
|
6158
|
my ($self, $sql, @bind) = @_; |
|
51
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
52
|
|
|
|
|
|
|
sql => $sql, |
|
53
|
|
|
|
|
|
|
bind => \@bind, |
|
54
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
55
|
5
|
|
|
|
|
35
|
); |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub func { |
|
59
|
34
|
|
|
34
|
1
|
26133
|
my ($self, $name, @args) = @_; |
|
60
|
34
|
50
|
|
|
|
220
|
confess "func name must be a word (\\w+), got '$name'" unless $name =~ /^\w+$/; |
|
61
|
|
|
|
|
|
|
# Coerce plain strings/values: strings in func args are column refs |
|
62
|
|
|
|
|
|
|
my @coerced = map { |
|
63
|
34
|
|
|
|
|
71
|
ref $_ ? $_ : SQL::Wizard::Expr::Column->new( |
|
64
|
|
|
|
|
|
|
name => $_, |
|
65
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
66
|
|
|
|
|
|
|
) |
|
67
|
31
|
100
|
|
|
|
190
|
} @args; |
|
68
|
|
|
|
|
|
|
SQL::Wizard::Expr::Func->new( |
|
69
|
|
|
|
|
|
|
name => $name, |
|
70
|
|
|
|
|
|
|
args => \@coerced, |
|
71
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
72
|
34
|
|
|
|
|
184
|
); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
## Query builders |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub select { |
|
78
|
125
|
|
|
125
|
0
|
64836
|
my ($self, %args) = @_; |
|
79
|
125
|
|
|
|
|
568
|
SQL::Wizard::Expr::Select->from_args(%args, _renderer => $self->{renderer}); |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub insert { |
|
83
|
7
|
|
|
7
|
0
|
1879
|
my ($self, %args) = @_; |
|
84
|
7
|
50
|
|
|
|
16
|
confess "insert requires -into" unless $args{'-into'}; |
|
85
|
7
|
|
|
|
|
9
|
my %node; |
|
86
|
7
|
50
|
|
|
|
19
|
$node{into} = $args{'-into'} if $args{'-into'}; |
|
87
|
7
|
100
|
|
|
|
17
|
$node{values} = $args{'-values'} if $args{'-values'}; |
|
88
|
7
|
100
|
|
|
|
14
|
$node{columns} = $args{'-columns'} if $args{'-columns'}; |
|
89
|
7
|
100
|
|
|
|
41
|
$node{select} = $args{'-select'} if $args{'-select'}; |
|
90
|
7
|
100
|
|
|
|
10
|
$node{on_conflict} = $args{'-on_conflict'} if $args{'-on_conflict'}; |
|
91
|
7
|
100
|
|
|
|
11
|
$node{on_duplicate} = $args{'-on_duplicate'} if $args{'-on_duplicate'}; |
|
92
|
7
|
100
|
|
|
|
12
|
$node{returning} = $args{'-returning'} if $args{'-returning'}; |
|
93
|
|
|
|
|
|
|
# Coerce hash values to Value nodes for bind params |
|
94
|
7
|
100
|
|
|
|
16
|
if (ref $node{values} eq 'HASH') { |
|
|
|
100
|
|
|
|
|
|
|
95
|
5
|
|
|
|
|
7
|
for my $k (keys %{$node{values}}) { |
|
|
5
|
|
|
|
|
12
|
|
|
96
|
9
|
|
|
|
|
11
|
my $v = $node{values}{$k}; |
|
97
|
9
|
100
|
|
|
|
13
|
next if ref $v; |
|
98
|
|
|
|
|
|
|
$node{values}{$k} = SQL::Wizard::Expr::Value->new( |
|
99
|
|
|
|
|
|
|
value => $v, |
|
100
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
101
|
8
|
|
|
|
|
23
|
); |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
} elsif (ref $node{values} eq 'ARRAY') { |
|
104
|
|
|
|
|
|
|
# Multi-row: coerce each cell |
|
105
|
1
|
|
|
|
|
32
|
for my $row (@{$node{values}}) { |
|
|
1
|
|
|
|
|
3
|
|
|
106
|
2
|
|
|
|
|
4
|
for my $i (0 .. $#$row) { |
|
107
|
4
|
50
|
|
|
|
7
|
next if ref $row->[$i]; |
|
108
|
|
|
|
|
|
|
$row->[$i] = SQL::Wizard::Expr::Value->new( |
|
109
|
|
|
|
|
|
|
value => $row->[$i], |
|
110
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
111
|
4
|
|
|
|
|
7
|
); |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
SQL::Wizard::Expr::Insert->new( |
|
116
|
|
|
|
|
|
|
%node, |
|
117
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
118
|
7
|
|
|
|
|
23
|
); |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub update { |
|
122
|
6
|
|
|
6
|
1
|
5816
|
my ($self, %args) = @_; |
|
123
|
6
|
50
|
|
|
|
14
|
confess "update requires -table" unless $args{'-table'}; |
|
124
|
6
|
50
|
|
|
|
11
|
confess "update requires -set" unless $args{'-set'}; |
|
125
|
6
|
|
|
|
|
6
|
my %node; |
|
126
|
6
|
50
|
|
|
|
15
|
$node{table} = $args{'-table'} if $args{'-table'}; |
|
127
|
6
|
50
|
|
|
|
14
|
$node{set} = $args{'-set'} if $args{'-set'}; |
|
128
|
6
|
100
|
|
|
|
11
|
$node{where} = $args{'-where'} if $args{'-where'}; |
|
129
|
6
|
100
|
|
|
|
11
|
$node{from} = $args{'-from'} if $args{'-from'}; |
|
130
|
6
|
100
|
|
|
|
8
|
$node{limit} = $args{'-limit'} if defined $args{'-limit'}; |
|
131
|
6
|
100
|
|
|
|
10
|
$node{returning} = $args{'-returning'} if $args{'-returning'}; |
|
132
|
|
|
|
|
|
|
# Coerce set values |
|
133
|
6
|
50
|
|
|
|
37
|
if (ref $node{set} eq 'HASH') { |
|
134
|
6
|
|
|
|
|
7
|
for my $k (keys %{$node{set}}) { |
|
|
6
|
|
|
|
|
14
|
|
|
135
|
7
|
|
|
|
|
10
|
my $v = $node{set}{$k}; |
|
136
|
7
|
100
|
|
|
|
14
|
next if ref $v; |
|
137
|
|
|
|
|
|
|
$node{set}{$k} = SQL::Wizard::Expr::Value->new( |
|
138
|
|
|
|
|
|
|
value => $v, |
|
139
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
140
|
4
|
|
|
|
|
45
|
); |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
} |
|
143
|
|
|
|
|
|
|
SQL::Wizard::Expr::Update->new( |
|
144
|
|
|
|
|
|
|
%node, |
|
145
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
146
|
6
|
|
|
|
|
24
|
); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub delete { |
|
150
|
6
|
|
|
6
|
1
|
3778
|
my ($self, %args) = @_; |
|
151
|
6
|
50
|
|
|
|
13
|
confess "delete requires -from" unless $args{'-from'}; |
|
152
|
6
|
|
|
|
|
9
|
my %node; |
|
153
|
6
|
50
|
|
|
|
13
|
$node{from} = $args{'-from'} if $args{'-from'}; |
|
154
|
6
|
100
|
|
|
|
13
|
$node{where} = $args{'-where'} if $args{'-where'}; |
|
155
|
6
|
100
|
|
|
|
10
|
$node{using} = $args{'-using'} if $args{'-using'}; |
|
156
|
6
|
100
|
|
|
|
10
|
$node{returning} = $args{'-returning'} if $args{'-returning'}; |
|
157
|
|
|
|
|
|
|
SQL::Wizard::Expr::Delete->new( |
|
158
|
|
|
|
|
|
|
%node, |
|
159
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
160
|
6
|
|
|
|
|
27
|
); |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub truncate { |
|
164
|
0
|
|
|
0
|
0
|
0
|
my ($self, %args) = @_; |
|
165
|
0
|
0
|
|
|
|
0
|
confess "truncate requires -table" unless $args{'-table'}; |
|
166
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
167
|
|
|
|
|
|
|
sql => '', |
|
168
|
|
|
|
|
|
|
bind => [], |
|
169
|
|
|
|
|
|
|
_truncate => $args{'-table'}, |
|
170
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
171
|
0
|
|
|
|
|
0
|
); |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
## Join helpers |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub join { |
|
177
|
7
|
|
|
7
|
0
|
3573
|
my ($self, $table, $on) = @_; |
|
178
|
|
|
|
|
|
|
SQL::Wizard::Expr::Join->new( |
|
179
|
|
|
|
|
|
|
type => 'JOIN', |
|
180
|
|
|
|
|
|
|
table => $table, |
|
181
|
|
|
|
|
|
|
on => $on, |
|
182
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
183
|
7
|
|
|
|
|
50
|
); |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub left_join { |
|
187
|
3
|
|
|
3
|
0
|
806
|
my ($self, $table, $on) = @_; |
|
188
|
|
|
|
|
|
|
SQL::Wizard::Expr::Join->new( |
|
189
|
|
|
|
|
|
|
type => 'LEFT JOIN', |
|
190
|
|
|
|
|
|
|
table => $table, |
|
191
|
|
|
|
|
|
|
on => $on, |
|
192
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
193
|
3
|
|
|
|
|
10
|
); |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub right_join { |
|
197
|
1
|
|
|
1
|
0
|
651
|
my ($self, $table, $on) = @_; |
|
198
|
|
|
|
|
|
|
SQL::Wizard::Expr::Join->new( |
|
199
|
|
|
|
|
|
|
type => 'RIGHT JOIN', |
|
200
|
|
|
|
|
|
|
table => $table, |
|
201
|
|
|
|
|
|
|
on => $on, |
|
202
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
203
|
1
|
|
|
|
|
5
|
); |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub full_join { |
|
207
|
1
|
|
|
1
|
0
|
569
|
my ($self, $table, $on) = @_; |
|
208
|
|
|
|
|
|
|
SQL::Wizard::Expr::Join->new( |
|
209
|
|
|
|
|
|
|
type => 'FULL OUTER JOIN', |
|
210
|
|
|
|
|
|
|
table => $table, |
|
211
|
|
|
|
|
|
|
on => $on, |
|
212
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
213
|
1
|
|
|
|
|
4
|
); |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub cross_join { |
|
217
|
1
|
|
|
1
|
0
|
548
|
my ($self, $table) = @_; |
|
218
|
|
|
|
|
|
|
SQL::Wizard::Expr::Join->new( |
|
219
|
|
|
|
|
|
|
type => 'CROSS JOIN', |
|
220
|
|
|
|
|
|
|
table => $table, |
|
221
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
222
|
1
|
|
|
|
|
4
|
); |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
## CASE expressions |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub case { |
|
228
|
5
|
|
|
5
|
0
|
12
|
my ($self, @args) = @_; |
|
229
|
5
|
|
|
|
|
8
|
my ($whens, $else) = $self->_parse_case_args(@args); |
|
230
|
|
|
|
|
|
|
SQL::Wizard::Expr::Case->new( |
|
231
|
|
|
|
|
|
|
whens => $whens, |
|
232
|
|
|
|
|
|
|
($else ? (else => $else) : ()), |
|
233
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
234
|
5
|
100
|
|
|
|
49
|
); |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub case_on { |
|
238
|
1
|
|
|
1
|
0
|
3
|
my ($self, $operand, @args) = @_; |
|
239
|
1
|
|
|
|
|
2
|
my ($whens, $else) = $self->_parse_case_args(@args); |
|
240
|
|
|
|
|
|
|
SQL::Wizard::Expr::Case->new( |
|
241
|
|
|
|
|
|
|
operand => $operand, |
|
242
|
|
|
|
|
|
|
whens => $whens, |
|
243
|
|
|
|
|
|
|
($else ? (else => $else) : ()), |
|
244
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
245
|
1
|
50
|
|
|
|
4
|
); |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub _parse_case_args { |
|
249
|
6
|
|
|
6
|
|
10
|
my ($self, @args) = @_; |
|
250
|
6
|
|
|
|
|
7
|
my @whens; |
|
251
|
|
|
|
|
|
|
my $else; |
|
252
|
6
|
|
|
|
|
12
|
for my $arg (@args) { |
|
253
|
14
|
100
|
33
|
|
|
37
|
if (ref $arg eq 'ARRAY') { |
|
|
|
50
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# [$q->when(...)] — a when clause |
|
255
|
9
|
|
|
|
|
13
|
push @whens, @$arg; |
|
256
|
|
|
|
|
|
|
} elsif (ref $arg eq 'HASH' && exists $arg->{_else}) { |
|
257
|
5
|
|
|
|
|
7
|
$else = $arg->{_else}; |
|
258
|
|
|
|
|
|
|
} |
|
259
|
|
|
|
|
|
|
} |
|
260
|
6
|
|
|
|
|
14
|
return (\@whens, $else); |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub when { |
|
264
|
9
|
|
|
9
|
1
|
3620
|
my ($self, $condition, $then) = @_; |
|
265
|
|
|
|
|
|
|
# Coerce then value |
|
266
|
9
|
100
|
|
|
|
29
|
$then = $self->val($then) unless ref $then; |
|
267
|
9
|
|
|
|
|
58
|
return { condition => $condition, then => $then }; |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub else { |
|
271
|
5
|
|
|
5
|
1
|
10
|
my ($self, $value) = @_; |
|
272
|
5
|
100
|
|
|
|
15
|
$value = $self->val($value) unless ref $value; |
|
273
|
5
|
|
|
|
|
16
|
return { _else => $value }; |
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
## Condition helpers |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub exists { |
|
279
|
2
|
|
|
2
|
1
|
30
|
my ($self, $subquery) = @_; |
|
280
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
281
|
|
|
|
|
|
|
sql => 'EXISTS', |
|
282
|
|
|
|
|
|
|
bind => [], |
|
283
|
|
|
|
|
|
|
_subquery => $subquery, |
|
284
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
285
|
2
|
|
|
|
|
18
|
); |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub not_exists { |
|
289
|
1
|
|
|
1
|
1
|
8
|
my ($self, $subquery) = @_; |
|
290
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
291
|
|
|
|
|
|
|
sql => 'NOT EXISTS', |
|
292
|
|
|
|
|
|
|
bind => [], |
|
293
|
|
|
|
|
|
|
_subquery => $subquery, |
|
294
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
295
|
1
|
|
|
|
|
8
|
); |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
sub any { |
|
299
|
2
|
|
|
2
|
1
|
15
|
my ($self, $subquery) = @_; |
|
300
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
301
|
|
|
|
|
|
|
sql => 'ANY', |
|
302
|
|
|
|
|
|
|
bind => [], |
|
303
|
|
|
|
|
|
|
_subquery => $subquery, |
|
304
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
305
|
2
|
|
|
|
|
13
|
); |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub all { |
|
309
|
2
|
|
|
2
|
1
|
16
|
my ($self, $subquery) = @_; |
|
310
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
311
|
|
|
|
|
|
|
sql => 'ALL', |
|
312
|
|
|
|
|
|
|
bind => [], |
|
313
|
|
|
|
|
|
|
_subquery => $subquery, |
|
314
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
315
|
2
|
|
|
|
|
18
|
); |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub between { |
|
319
|
1
|
|
|
1
|
1
|
816
|
my ($self, $col, $lo, $hi) = @_; |
|
320
|
1
|
50
|
|
|
|
9
|
$col = $self->col($col) unless ref $col; |
|
321
|
1
|
50
|
|
|
|
8
|
$lo = $self->val($lo) unless ref $lo; |
|
322
|
1
|
50
|
|
|
|
5
|
$hi = $self->val($hi) unless ref $hi; |
|
323
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
324
|
|
|
|
|
|
|
sql => 'BETWEEN', |
|
325
|
|
|
|
|
|
|
bind => [], |
|
326
|
|
|
|
|
|
|
_between => { col => $col, lo => $lo, hi => $hi }, |
|
327
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
328
|
1
|
|
|
|
|
37
|
); |
|
329
|
|
|
|
|
|
|
} |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub not_between { |
|
332
|
1
|
|
|
1
|
1
|
1679
|
my ($self, $col, $lo, $hi) = @_; |
|
333
|
1
|
50
|
|
|
|
8
|
$col = $self->col($col) unless ref $col; |
|
334
|
1
|
50
|
|
|
|
7
|
$lo = $self->val($lo) unless ref $lo; |
|
335
|
1
|
50
|
|
|
|
4
|
$hi = $self->val($hi) unless ref $hi; |
|
336
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
337
|
|
|
|
|
|
|
sql => 'NOT BETWEEN', |
|
338
|
|
|
|
|
|
|
bind => [], |
|
339
|
|
|
|
|
|
|
_not_between => { col => $col, lo => $lo, hi => $hi }, |
|
340
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
341
|
1
|
|
|
|
|
11
|
); |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub compare { |
|
345
|
4
|
|
|
4
|
1
|
2125
|
my ($self, $left, $op, $right) = @_; |
|
346
|
4
|
100
|
66
|
|
|
23
|
$left = $self->col($left) if (!ref $left && $left =~ /^[\w.]+$/); |
|
347
|
4
|
50
|
|
|
|
8
|
$left = $self->val($left) if (!ref $left); |
|
348
|
4
|
100
|
|
|
|
9
|
$right = $self->val($right) if (!ref $right); |
|
349
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
350
|
|
|
|
|
|
|
sql => '', |
|
351
|
|
|
|
|
|
|
bind => [], |
|
352
|
|
|
|
|
|
|
_compare => { left => $left, op => $op, right => $right }, |
|
353
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
354
|
4
|
|
|
|
|
21
|
); |
|
355
|
|
|
|
|
|
|
} |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
## Function shortcuts |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub cast { |
|
360
|
1
|
|
|
1
|
1
|
1648
|
my ($self, $expr, $type) = @_; |
|
361
|
1
|
50
|
|
|
|
8
|
$expr = $self->col($expr) unless ref $expr; |
|
362
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
363
|
|
|
|
|
|
|
sql => "CAST", |
|
364
|
|
|
|
|
|
|
bind => [], |
|
365
|
|
|
|
|
|
|
_cast => { expr => $expr, type => $type }, |
|
366
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
367
|
1
|
|
|
|
|
10
|
); |
|
368
|
|
|
|
|
|
|
} |
|
369
|
|
|
|
|
|
|
|
|
370
|
1
|
|
|
1
|
1
|
3
|
sub coalesce { my $self = shift; $self->func('COALESCE', @_) } |
|
|
1
|
|
|
|
|
6
|
|
|
371
|
1
|
|
|
1
|
1
|
1729
|
sub greatest { my $self = shift; $self->func('GREATEST', @_) } |
|
|
1
|
|
|
|
|
6
|
|
|
372
|
1
|
|
|
1
|
1
|
940
|
sub least { my $self = shift; $self->func('LEAST', @_) } |
|
|
1
|
|
|
|
|
5
|
|
|
373
|
2
|
|
|
2
|
1
|
586
|
sub now { my $self = shift; $self->func('NOW') } |
|
|
2
|
|
|
|
|
8
|
|
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
## Boolean operators |
|
376
|
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub and { |
|
378
|
1
|
|
|
1
|
1
|
1715
|
my ($self, @conds) = @_; |
|
379
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
380
|
|
|
|
|
|
|
sql => 'AND', |
|
381
|
|
|
|
|
|
|
bind => [], |
|
382
|
|
|
|
|
|
|
_logic => { op => 'AND', conds => \@conds }, |
|
383
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
384
|
1
|
|
|
|
|
11
|
); |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub or { |
|
388
|
1
|
|
|
1
|
1
|
1735
|
my ($self, @conds) = @_; |
|
389
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
390
|
|
|
|
|
|
|
sql => 'OR', |
|
391
|
|
|
|
|
|
|
bind => [], |
|
392
|
|
|
|
|
|
|
_logic => { op => 'OR', conds => \@conds }, |
|
393
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
394
|
1
|
|
|
|
|
10
|
); |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
sub not { |
|
398
|
1
|
|
|
1
|
1
|
1674
|
my ($self, $cond) = @_; |
|
399
|
|
|
|
|
|
|
SQL::Wizard::Expr::Raw->new( |
|
400
|
|
|
|
|
|
|
sql => 'NOT', |
|
401
|
|
|
|
|
|
|
bind => [], |
|
402
|
|
|
|
|
|
|
_not => $cond, |
|
403
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
404
|
1
|
|
|
|
|
9
|
); |
|
405
|
|
|
|
|
|
|
} |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
## CTEs |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
sub with { |
|
410
|
3
|
|
|
3
|
1
|
11
|
my ($self, @args) = @_; |
|
411
|
3
|
|
|
|
|
6
|
my @ctes; |
|
412
|
3
|
|
|
|
|
9
|
while (@args) { |
|
413
|
4
|
|
|
|
|
7
|
my $name = shift @args; |
|
414
|
4
|
|
|
|
|
7
|
my $query = shift @args; |
|
415
|
4
|
|
|
|
|
17
|
push @ctes, { name => $name, query => $query }; |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
SQL::Wizard::Expr::CTE->new( |
|
418
|
|
|
|
|
|
|
ctes => \@ctes, |
|
419
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
420
|
3
|
|
|
|
|
19
|
); |
|
421
|
|
|
|
|
|
|
} |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
sub with_recursive { |
|
424
|
1
|
|
|
1
|
1
|
5
|
my ($self, @args) = @_; |
|
425
|
1
|
|
|
|
|
3
|
my @ctes; |
|
426
|
1
|
|
|
|
|
6
|
while (@args) { |
|
427
|
1
|
|
|
|
|
3
|
my $name = shift @args; |
|
428
|
1
|
|
|
|
|
2
|
my $query = shift @args; |
|
429
|
1
|
|
|
|
|
7
|
push @ctes, { name => $name, query => $query }; |
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
SQL::Wizard::Expr::CTE->new( |
|
432
|
|
|
|
|
|
|
ctes => \@ctes, |
|
433
|
|
|
|
|
|
|
recursive => 1, |
|
434
|
|
|
|
|
|
|
_renderer => $self->{renderer}, |
|
435
|
1
|
|
|
|
|
7
|
); |
|
436
|
|
|
|
|
|
|
} |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
1; |