line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DBIx::Perlish; |
2
|
|
|
|
|
|
|
|
3
|
25
|
|
|
25
|
|
742620
|
use 5.014; |
|
25
|
|
|
|
|
246
|
|
4
|
25
|
|
|
25
|
|
166
|
use warnings; |
|
25
|
|
|
|
|
49
|
|
|
25
|
|
|
|
|
708
|
|
5
|
25
|
|
|
25
|
|
136
|
use strict; |
|
25
|
|
|
|
|
63
|
|
|
25
|
|
|
|
|
658
|
|
6
|
25
|
|
|
25
|
|
121
|
use Carp; |
|
25
|
|
|
|
|
57
|
|
|
25
|
|
|
|
|
2453
|
|
7
|
|
|
|
|
|
|
|
8
|
25
|
|
|
25
|
|
161
|
use vars qw($VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS $SQL @BIND_VALUES); |
|
25
|
|
|
|
|
61
|
|
|
25
|
|
|
|
|
2941
|
|
9
|
|
|
|
|
|
|
require Exporter; |
10
|
25
|
|
|
25
|
|
156
|
use base 'Exporter'; |
|
25
|
|
|
|
|
87
|
|
|
25
|
|
|
|
|
2192
|
|
11
|
25
|
|
|
25
|
|
11331
|
use Keyword::Pluggable; |
|
25
|
|
|
|
|
631695
|
|
|
25
|
|
|
|
|
1694
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
$VERSION = '1.07'; |
14
|
|
|
|
|
|
|
@EXPORT = qw(sql); |
15
|
|
|
|
|
|
|
@EXPORT_OK = qw(union intersect except subselect); |
16
|
|
|
|
|
|
|
%EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); |
17
|
|
|
|
|
|
|
|
18
|
25
|
|
|
25
|
|
16286
|
use DBIx::Perlish::Parse; |
|
25
|
|
|
|
|
113
|
|
|
25
|
|
|
|
|
7510
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
0
|
1
|
|
sub union (&;$) {} |
21
|
|
|
|
0
|
1
|
|
sub intersect (&;$) {} |
22
|
|
|
|
0
|
1
|
|
sub except (&;$) {} |
23
|
|
|
|
0
|
1
|
|
sub subselect (&) {} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $default_object; |
26
|
|
|
|
|
|
|
my $non_object_quirks = {}; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub optree_version |
29
|
|
|
|
|
|
|
{ |
30
|
3
|
50
|
|
3
|
1
|
3440
|
return 1 if $^V lt 5.22.0; |
31
|
3
|
|
|
|
|
13
|
return 2; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub lexify |
35
|
|
|
|
|
|
|
{ |
36
|
32
|
|
|
32
|
0
|
133
|
my ( $text, $insert ) = @_; |
37
|
32
|
100
|
|
|
|
184
|
$insert .= 'sub ' if $$text =~ /^\s*\{/; |
38
|
32
|
|
|
|
|
5033
|
substr($$text, 0, 0, $insert); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub import |
42
|
|
|
|
|
|
|
{ |
43
|
27
|
|
|
27
|
|
2199
|
my $pkg = caller; |
44
|
27
|
|
|
|
|
84
|
local @EXPORT_OK = @EXPORT_OK; |
45
|
27
|
|
|
|
|
130
|
local %EXPORT_TAGS = %EXPORT_TAGS; |
46
|
27
|
50
|
33
|
|
|
441
|
if ($pkg && $pkg->can("except")) { |
47
|
|
|
|
|
|
|
# XXX maybe check prototype here |
48
|
0
|
|
|
|
|
0
|
pop @EXPORT_OK; |
49
|
0
|
|
|
|
|
0
|
%EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); |
50
|
|
|
|
|
|
|
} |
51
|
27
|
|
|
|
|
55
|
my @shift; |
52
|
27
|
100
|
|
|
|
147
|
@shift = (shift()) if @_ % 2; |
53
|
27
|
|
|
|
|
88
|
my %p = @_; |
54
|
27
|
100
|
66
|
|
|
119
|
if ($p{prefix} && $p{prefix} =~ /^[a-zA-Z_]\w*$/) { |
55
|
25
|
|
|
25
|
|
190
|
no strict 'refs'; |
|
25
|
|
|
|
|
92
|
|
|
25
|
|
|
|
|
11972
|
|
56
|
2
|
50
|
33
|
|
|
17
|
if ( $p{dbh} && ref $p{dbh} && (ref $p{dbh} eq "SCALAR" || ref $p{dbh} eq "REF")) { |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
57
|
2
|
|
|
|
|
4
|
my $dbhref = $p{dbh}; |
58
|
2
|
|
|
|
|
53
|
*{$pkg."::$p{prefix}_fetch"} = |
59
|
2
|
|
|
|
|
12
|
*{$pkg."::$p{prefix}_select"} = |
60
|
2
|
|
|
0
|
|
7
|
sub (&) { my $o = DBIx::Perlish->new(dbh => $$dbhref); $o->fetch(@_) }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
61
|
2
|
|
|
|
|
7
|
*{$pkg."::$p{prefix}_update"} = |
62
|
2
|
|
|
0
|
|
14
|
sub (&) { my $o = DBIx::Perlish->new(dbh => $$dbhref); $o->update(@_) }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
63
|
2
|
|
|
|
|
7
|
*{$pkg."::$p{prefix}_delete"} = |
64
|
2
|
|
|
0
|
|
18
|
sub (&) { my $o = DBIx::Perlish->new(dbh => $$dbhref); $o->delete(@_) }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
65
|
2
|
|
|
|
|
8
|
*{$pkg."::$p{prefix}_insert"} = |
66
|
2
|
|
|
0
|
|
4
|
sub { my $o = DBIx::Perlish->new(dbh => $$dbhref); $o->insert(@_) }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
67
|
2
|
|
|
|
|
207
|
return; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
25
|
|
50
|
|
|
139
|
my $prefix = delete($p{prefix}) // 'db'; |
72
|
25
|
|
100
|
|
|
133
|
my $dbh = delete($p{dbh}) // '$dbh'; |
73
|
25
|
|
|
|
|
78
|
my $iprefix = '__' . $dbh . '_execute_perlish'; |
74
|
25
|
|
|
|
|
183
|
$iprefix =~ s/\W//g; |
75
|
|
|
|
|
|
|
|
76
|
25
|
|
|
|
|
157
|
for ( |
77
|
|
|
|
|
|
|
[fetch => " $dbh, q(fetch), "], |
78
|
|
|
|
|
|
|
[select => " $dbh, q(fetch), "], |
79
|
|
|
|
|
|
|
[update => " $dbh, q(update), "], |
80
|
|
|
|
|
|
|
[delete => " $dbh, q(delete), "], |
81
|
|
|
|
|
|
|
) { |
82
|
100
|
|
|
|
|
2112
|
my ($name, $code) = @$_; |
83
|
|
|
|
|
|
|
Keyword::Pluggable::define |
84
|
|
|
|
|
|
|
keyword => $prefix . '_' . $name, |
85
|
32
|
|
|
32
|
|
3138
|
code => sub { lexify( $_[0], $iprefix.$code ) }, |
86
|
100
|
|
|
|
|
512
|
expression => 1, |
87
|
|
|
|
|
|
|
package => $pkg |
88
|
|
|
|
|
|
|
; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
Keyword::Pluggable::define |
91
|
25
|
|
|
|
|
634
|
keyword => $prefix . '_insert', |
92
|
|
|
|
|
|
|
code => $iprefix . "_insert $dbh, ", |
93
|
|
|
|
|
|
|
expression => 1, |
94
|
|
|
|
|
|
|
package => $pkg |
95
|
|
|
|
|
|
|
; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
{ |
98
|
25
|
|
|
25
|
|
190
|
no strict 'refs'; |
|
25
|
|
|
|
|
49
|
|
|
25
|
|
|
|
|
81702
|
|
|
25
|
|
|
|
|
579
|
|
99
|
25
|
|
|
|
|
228
|
*{$pkg."::${iprefix}"} = sub ($$&) { |
100
|
3
|
|
|
3
|
|
25
|
my ( $dbh, $method, $sub ) = @_; |
101
|
3
|
|
|
|
|
14
|
my $o = DBIx::Perlish->new(dbh => $dbh); |
102
|
3
|
|
|
|
|
9
|
$o->$method($sub); |
103
|
25
|
|
|
|
|
100
|
}; |
104
|
25
|
|
|
|
|
134
|
*{$pkg."::${iprefix}_insert"} = sub { |
105
|
0
|
|
|
0
|
|
0
|
my $o = DBIx::Perlish->new(dbh => shift); |
106
|
0
|
|
|
|
|
0
|
$o->insert(@_) |
107
|
25
|
|
|
|
|
96
|
}; |
108
|
|
|
|
|
|
|
} |
109
|
25
|
|
|
|
|
5105
|
DBIx::Perlish->export_to_level(1, @shift, %p); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
0
|
0
|
0
|
sub init { warn "DBIx::Perlish::init is deprecated" } |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub new |
115
|
|
|
|
|
|
|
{ |
116
|
5
|
|
|
5
|
1
|
1510
|
my ($class, %p) = @_; |
117
|
5
|
100
|
|
|
|
26
|
unless (UNIVERSAL::isa($p{dbh}, "DBI::db")) { # XXX maybe relax for other things? |
118
|
1
|
|
|
|
|
13
|
die "Invalid database handle supplied in the \"dbh\" parameter.\n"; |
119
|
|
|
|
|
|
|
} |
120
|
4
|
|
|
|
|
21
|
my $me = bless { dbh => $p{dbh}, quirks => {} }, $class; |
121
|
4
|
50
|
33
|
|
|
16
|
if ($p{quirks} && ref $p{quirks} eq "ARRAY") { |
122
|
0
|
|
|
|
|
0
|
for my $q (@{$p{quirks}}) { |
|
0
|
|
|
|
|
0
|
|
123
|
0
|
|
|
|
|
0
|
$me->quirk(@$q); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
} |
126
|
4
|
|
|
|
|
17
|
return $me; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub quirk |
130
|
|
|
|
|
|
|
{ |
131
|
0
|
|
|
0
|
1
|
0
|
my $flavor = shift; |
132
|
0
|
|
|
|
|
0
|
my $quirks = $non_object_quirks; |
133
|
0
|
0
|
|
|
|
0
|
if (ref $flavor) { |
134
|
0
|
|
|
|
|
0
|
$quirks = $flavor->{quirks}; |
135
|
0
|
|
|
|
|
0
|
$flavor = shift; |
136
|
|
|
|
|
|
|
} |
137
|
0
|
|
|
|
|
0
|
$flavor = lc $flavor; |
138
|
0
|
0
|
|
|
|
0
|
if ($flavor eq "oracle") { |
139
|
0
|
|
|
|
|
0
|
my $qtype = shift; |
140
|
0
|
0
|
|
|
|
0
|
if ($qtype eq "table_func_cast") { |
141
|
0
|
|
|
|
|
0
|
my ($func, $cast) = @_; |
142
|
0
|
0
|
|
|
|
0
|
die "table_func_cast requires a function name and a type name" unless $cast; |
143
|
0
|
|
|
|
|
0
|
$quirks->{oracle_table_func_cast}{$func} = $cast; |
144
|
|
|
|
|
|
|
} else { |
145
|
0
|
|
|
|
|
0
|
die "unknown quirk $qtype for $flavor"; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} else { |
148
|
0
|
|
|
|
|
0
|
die "there are currently no quirks for $flavor"; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub _get_flavor |
153
|
|
|
|
|
|
|
{ |
154
|
3
|
|
|
3
|
|
7
|
my ($real_dbh) = @_; |
155
|
3
|
|
33
|
|
|
12
|
my $dbh = tied(%$real_dbh) || $real_dbh; |
156
|
3
|
|
|
|
|
12
|
return lc $dbh->{Driver}{Name}; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub gen_sql_select |
160
|
|
|
|
|
|
|
{ |
161
|
3
|
|
|
3
|
0
|
4
|
my ($moi, $sub) = @_; |
162
|
3
|
50
|
|
|
|
7
|
my $me = ref $moi ? $moi : {}; |
163
|
|
|
|
|
|
|
|
164
|
3
|
|
|
|
|
4
|
my $dbh = $me->{dbh}; |
165
|
3
|
|
|
|
|
5
|
my @kf; |
166
|
3
|
|
|
|
|
5
|
my $flavor = _get_flavor($dbh); |
167
|
3
|
|
|
0
|
|
10
|
my $kf_convert = sub { return $_[0] }; |
|
0
|
|
|
|
|
0
|
|
168
|
3
|
0
|
33
|
|
|
8
|
if ($flavor eq "pg" && $dbh->{FetchHashKeyName}) { |
169
|
0
|
0
|
|
|
|
0
|
if ($dbh->{FetchHashKeyName} eq "NAME_uc") { |
|
|
0
|
|
|
|
|
|
170
|
0
|
|
|
0
|
|
0
|
$kf_convert = sub { return uc $_[0] }; |
|
0
|
|
|
|
|
0
|
|
171
|
|
|
|
|
|
|
} elsif ($dbh->{FetchHashKeyName} eq "NAME_lc") { |
172
|
0
|
|
|
0
|
|
0
|
$kf_convert = sub { return lc $_[0] }; |
|
0
|
|
|
|
|
0
|
|
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
my ($sql, $bind_values, $nret, %flags) = gen_sql($sub, "select", |
176
|
|
|
|
|
|
|
flavor => $flavor, |
177
|
|
|
|
|
|
|
dbh => $dbh, |
178
|
3
|
|
33
|
|
|
11
|
quirks => $me->{quirks} || $non_object_quirks, |
179
|
|
|
|
|
|
|
key_fields => \@kf, |
180
|
|
|
|
|
|
|
kf_convert => $kf_convert, |
181
|
|
|
|
|
|
|
); |
182
|
3
|
50
|
|
|
|
8
|
$flags{key_fields} = \@kf if @kf; |
183
|
3
|
|
|
|
|
18
|
return $sql, $bind_values, $nret, %flags; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub query |
187
|
|
|
|
|
|
|
{ |
188
|
0
|
|
|
0
|
1
|
0
|
my ($moi, $sub) = @_; |
189
|
0
|
0
|
|
|
|
0
|
my $me = ref $moi ? $moi : {}; |
190
|
0
|
|
|
|
|
0
|
my ( $sql ) = $moi->gen_sql_select($sub); |
191
|
0
|
|
|
|
|
0
|
return $sql; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub fetch |
195
|
|
|
|
|
|
|
{ |
196
|
3
|
|
|
3
|
1
|
6
|
my ($moi, $sub) = @_; |
197
|
3
|
50
|
|
|
|
8
|
my $me = ref $moi ? $moi : {}; |
198
|
|
|
|
|
|
|
|
199
|
3
|
|
|
|
|
3
|
my $nret; |
200
|
3
|
|
|
|
|
9
|
my $dbh = $me->{dbh}; |
201
|
3
|
|
|
|
|
4
|
my %flags; |
202
|
|
|
|
|
|
|
|
203
|
3
|
|
|
|
|
9
|
($me->{sql}, $me->{bind_values}, $nret, %flags) = $me->gen_sql_select($sub); |
204
|
3
|
|
|
|
|
6
|
$SQL = $me->{sql}; @BIND_VALUES = @{$me->{bind_values}}; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
5
|
|
205
|
|
|
|
|
|
|
|
206
|
3
|
50
|
|
|
|
6
|
if ($flags{key_fields}) { |
207
|
0
|
|
0
|
|
|
0
|
my @kf = @{ $flags{key_fields} // [] }; |
|
0
|
|
|
|
|
0
|
|
208
|
0
|
0
|
|
|
|
0
|
my $kf = @kf == 1 ? $kf[0] : [@kf]; |
209
|
0
|
|
0
|
|
|
0
|
my $r = $dbh->selectall_hashref($me->{sql}, $kf, {}, @{$me->{bind_values}}) || {}; |
210
|
0
|
|
|
|
|
0
|
my $postprocess; |
211
|
0
|
0
|
|
|
|
0
|
if ($nret - @kf == 1) { |
212
|
|
|
|
|
|
|
# Only one field returned apart from the key field, |
213
|
|
|
|
|
|
|
# change hash reference to simple values. |
214
|
|
|
|
|
|
|
$postprocess = sub { |
215
|
0
|
|
|
0
|
|
0
|
my ($h, $level) = @_; |
216
|
0
|
0
|
|
|
|
0
|
if ($level <= 1) { |
217
|
0
|
|
|
|
|
0
|
delete @$_{@kf} for values %$h; |
218
|
0
|
|
|
|
|
0
|
$_ = (values %$_)[0] for values %$h; |
219
|
|
|
|
|
|
|
} else { |
220
|
0
|
|
|
|
|
0
|
for my $nh (values %$h) { |
221
|
0
|
|
|
|
|
0
|
$postprocess->($nh, $level-1); |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
} |
224
|
0
|
|
|
|
|
0
|
}; |
225
|
|
|
|
|
|
|
} else { |
226
|
|
|
|
|
|
|
$postprocess = sub { |
227
|
0
|
|
|
0
|
|
0
|
my ($h, $level) = @_; |
228
|
0
|
0
|
|
|
|
0
|
if ($level <= 1) { |
229
|
0
|
|
|
|
|
0
|
delete @$_{@kf} for values %$h; |
230
|
|
|
|
|
|
|
} else { |
231
|
0
|
|
|
|
|
0
|
for my $nh (values %$h) { |
232
|
0
|
|
|
|
|
0
|
$postprocess->($nh, $level-1); |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
} |
235
|
0
|
|
|
|
|
0
|
}; |
236
|
|
|
|
|
|
|
} |
237
|
0
|
|
|
|
|
0
|
$postprocess->($r, scalar @kf); |
238
|
0
|
0
|
|
|
|
0
|
return wantarray ? %$r : $r; |
239
|
|
|
|
|
|
|
} else { |
240
|
3
|
50
|
|
|
|
8
|
if ($nret > 1) { |
241
|
0
|
|
0
|
|
|
0
|
my $r = $dbh->selectall_arrayref($me->{sql}, {Slice=>{}}, @{$me->{bind_values}}) || []; |
242
|
0
|
0
|
|
|
|
0
|
return wantarray ? @$r : $r->[0]; |
243
|
|
|
|
|
|
|
} else { |
244
|
3
|
|
50
|
|
|
5
|
my $r = $dbh->selectcol_arrayref($me->{sql}, {}, @{$me->{bind_values}}) || []; |
245
|
3
|
50
|
|
|
|
49
|
return wantarray ? @$r : $r->[0]; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# XXX refactor update/delete into a single implemention if possible? |
251
|
|
|
|
|
|
|
sub update |
252
|
|
|
|
|
|
|
{ |
253
|
0
|
|
|
0
|
1
|
0
|
my ($moi, $sub) = @_; |
254
|
0
|
0
|
|
|
|
0
|
my $me = ref $moi ? $moi : {}; |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
0
|
my $dbh = $me->{dbh}; |
257
|
|
|
|
|
|
|
($me->{sql}, $me->{bind_values}) = gen_sql($sub, "update", |
258
|
|
|
|
|
|
|
flavor => _get_flavor($dbh), |
259
|
|
|
|
|
|
|
dbh => $dbh, |
260
|
0
|
|
0
|
|
|
0
|
quirks => $me->{quirks} || $non_object_quirks, |
261
|
|
|
|
|
|
|
); |
262
|
0
|
|
|
|
|
0
|
$SQL = $me->{sql}; @BIND_VALUES = @{$me->{bind_values}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
263
|
0
|
|
|
|
|
0
|
$dbh->do($me->{sql}, {}, @{$me->{bind_values}}); |
|
0
|
|
|
|
|
0
|
|
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
sub delete |
267
|
|
|
|
|
|
|
{ |
268
|
0
|
|
|
0
|
1
|
0
|
my ($moi, $sub) = @_; |
269
|
0
|
0
|
|
|
|
0
|
my $me = ref $moi ? $moi : {}; |
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
0
|
my $dbh = $me->{dbh}; |
272
|
|
|
|
|
|
|
($me->{sql}, $me->{bind_values}) = gen_sql($sub, "delete", |
273
|
|
|
|
|
|
|
flavor => _get_flavor($dbh), |
274
|
|
|
|
|
|
|
dbh => $dbh, |
275
|
0
|
|
0
|
|
|
0
|
quirks => $me->{quirks} || $non_object_quirks, |
276
|
|
|
|
|
|
|
); |
277
|
0
|
|
|
|
|
0
|
$SQL = $me->{sql}; @BIND_VALUES = @{$me->{bind_values}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
278
|
0
|
|
|
|
|
0
|
$dbh->do($me->{sql}, {}, @{$me->{bind_values}}); |
|
0
|
|
|
|
|
0
|
|
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub insert |
282
|
|
|
|
|
|
|
{ |
283
|
0
|
|
|
0
|
1
|
0
|
my ($moi, $table, @rows) = @_; |
284
|
0
|
0
|
|
|
|
0
|
my $me = ref $moi ? $moi : {}; |
285
|
|
|
|
|
|
|
|
286
|
0
|
|
|
|
|
0
|
my $dbh = $me->{dbh}; |
287
|
0
|
|
|
|
|
0
|
my %sth; |
288
|
0
|
|
|
|
|
0
|
for my $row (@rows) { |
289
|
0
|
|
|
|
|
0
|
my @keys = sort keys %$row; |
290
|
0
|
|
|
|
|
0
|
my $sql = "insert into $table ("; |
291
|
0
|
|
|
|
|
0
|
$sql .= join ",", @keys; |
292
|
0
|
|
|
|
|
0
|
$sql .= ") values ("; |
293
|
0
|
|
|
|
|
0
|
my (@v, @b); |
294
|
0
|
|
|
|
|
0
|
my $skip_prepare; |
295
|
0
|
|
|
|
|
0
|
for my $v (@$row{@keys}) { |
296
|
0
|
0
|
|
|
|
0
|
if (ref $v eq 'CODE') { |
297
|
0
|
|
|
|
|
0
|
push @v, scalar $v->(); |
298
|
0
|
|
|
|
|
0
|
$skip_prepare = 1; |
299
|
|
|
|
|
|
|
} else { |
300
|
0
|
|
|
|
|
0
|
push @v, "?"; |
301
|
0
|
|
|
|
|
0
|
push @b, $v; |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
} |
304
|
0
|
|
|
|
|
0
|
$sql .= join ",", @v; |
305
|
0
|
|
|
|
|
0
|
$sql .= ")"; |
306
|
0
|
0
|
|
|
|
0
|
if ($skip_prepare) { |
307
|
0
|
0
|
|
|
|
0
|
return undef unless defined $dbh->do($sql, {}, @b); |
308
|
|
|
|
|
|
|
} else { |
309
|
0
|
|
|
|
|
0
|
my $k = join ";", @keys; |
310
|
0
|
|
0
|
|
|
0
|
$sth{$k} ||= $dbh->prepare($sql); |
311
|
0
|
0
|
|
|
|
0
|
return undef unless defined $sth{$k}->execute(@b); |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
} |
314
|
0
|
|
|
|
|
0
|
return scalar @rows; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
sub sql ($) { |
318
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
319
|
0
|
0
|
0
|
|
|
0
|
if (ref $self && $self->isa("DBIx::Perlish")) { |
320
|
0
|
|
|
|
|
0
|
$self->{sql}; |
321
|
|
|
|
|
|
|
} else { |
322
|
0
|
|
|
0
|
|
0
|
sub { $self } |
323
|
0
|
|
|
|
|
0
|
} |
324
|
|
|
|
|
|
|
} |
325
|
0
|
0
|
|
0
|
1
|
0
|
sub bind_values { $_[0]->{bind_values} ? @{$_[0]->{bind_values}} : () } |
|
0
|
|
|
|
|
0
|
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub gen_sql |
328
|
|
|
|
|
|
|
{ |
329
|
346
|
|
|
346
|
0
|
431827
|
my ($sub, $operation, %args) = @_; |
330
|
|
|
|
|
|
|
|
331
|
346
|
100
|
|
|
|
1579
|
$args{quirks} = $non_object_quirks unless $args{quirks}; |
332
|
346
|
|
100
|
|
|
1664
|
$args{inline} //= 1; |
333
|
|
|
|
|
|
|
|
334
|
346
|
|
|
|
|
1383
|
my $S = DBIx::Perlish::Parse::init(%args, operation => $operation); |
335
|
346
|
|
|
|
|
1167
|
DBIx::Perlish::Parse::parse_sub($S, $sub); |
336
|
289
|
|
|
|
|
812
|
my $sql = ""; |
337
|
289
|
|
|
|
|
452
|
my $next_bit = ""; |
338
|
289
|
|
|
|
|
419
|
my $nret = 9999; |
339
|
289
|
|
|
|
|
656
|
my $no_aliases; |
340
|
|
|
|
|
|
|
my $dangerous; |
341
|
289
|
|
|
|
|
0
|
my %flags; |
342
|
289
|
100
|
|
|
|
691
|
if ($operation eq "select") { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
343
|
261
|
|
|
|
|
359
|
my $nkf = 0; |
344
|
261
|
100
|
|
|
|
606
|
if ($S->{key_fields}) { |
345
|
7
|
|
|
|
|
10
|
$nkf = @{$S->{key_fields}}; |
|
7
|
|
|
|
|
15
|
|
346
|
7
|
100
|
|
|
|
16
|
push @{$args{key_fields}}, @{$S->{key_fields}} if $args{key_fields}; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
11
|
|
347
|
|
|
|
|
|
|
} |
348
|
261
|
|
|
|
|
451
|
$sql = "select "; |
349
|
261
|
100
|
|
|
|
575
|
$sql .= "distinct " if $S->{distinct}; |
350
|
261
|
100
|
|
|
|
519
|
if ($S->{returns}) { |
351
|
83
|
|
|
|
|
143
|
$sql .= join ", ", @{$S->{returns}}; |
|
83
|
|
|
|
|
269
|
|
352
|
83
|
|
|
|
|
133
|
$nret = @{$S->{returns}}; |
|
83
|
|
|
|
|
170
|
|
353
|
83
|
|
|
|
|
182
|
for my $ret (@{$S->{returns}}) { |
|
83
|
|
|
|
|
171
|
|
354
|
121
|
100
|
|
|
|
411
|
$nret = 9999 if $ret =~ /\*/; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
$flags{returns_dont_care} = 1 if |
357
|
83
|
|
|
|
|
490
|
1 == @{$S->{returns}} && |
358
|
|
|
|
|
|
|
$S->{returns}->[0] =~ /^(.*)\.\*/ && |
359
|
83
|
100
|
100
|
|
|
149
|
$S->{returns_dont_care}->{$1} |
|
|
|
100
|
|
|
|
|
360
|
|
|
|
|
|
|
; |
361
|
|
|
|
|
|
|
} else { |
362
|
178
|
|
|
|
|
478
|
$sql .= "*"; |
363
|
|
|
|
|
|
|
} |
364
|
261
|
|
|
|
|
433
|
$next_bit = " from "; |
365
|
261
|
100
|
|
|
|
615
|
die "all returns are key fields, this is nonsensical\n" if $nkf == $nret; |
366
|
|
|
|
|
|
|
} elsif ($operation eq "delete") { |
367
|
2
|
|
|
|
|
4
|
$no_aliases = 1; |
368
|
2
|
|
|
|
|
4
|
$dangerous = 1; |
369
|
2
|
|
|
|
|
3
|
$next_bit = "delete from "; |
370
|
|
|
|
|
|
|
} elsif ($operation eq "update") { |
371
|
26
|
|
|
|
|
40
|
$no_aliases = 1; |
372
|
26
|
|
|
|
|
61
|
$dangerous = 1; |
373
|
26
|
|
|
|
|
44
|
$next_bit = "update "; |
374
|
|
|
|
|
|
|
} else { |
375
|
0
|
|
|
|
|
0
|
die "unsupported operation: $operation\n"; |
376
|
|
|
|
|
|
|
} |
377
|
287
|
|
|
|
|
412
|
my %tabs; |
378
|
287
|
|
|
|
|
377
|
for my $var (keys %{$S->{vars}}) { |
|
287
|
|
|
|
|
1077
|
|
379
|
191
|
100
|
|
|
|
905
|
$tabs{$S->{var_alias}->{$var}} = |
380
|
|
|
|
|
|
|
$no_aliases ? |
381
|
|
|
|
|
|
|
"$S->{vars}->{$var}" : |
382
|
|
|
|
|
|
|
"$S->{vars}->{$var} $S->{var_alias}->{$var}"; |
383
|
|
|
|
|
|
|
} |
384
|
287
|
|
|
|
|
522
|
for my $tab (keys %{$S->{tabs}}) { |
|
287
|
|
|
|
|
889
|
|
385
|
130
|
100
|
|
|
|
585
|
$tabs{$S->{tab_alias}->{$tab}} = |
386
|
|
|
|
|
|
|
$no_aliases ? |
387
|
|
|
|
|
|
|
"$tab" : |
388
|
|
|
|
|
|
|
"$tab $S->{tab_alias}->{$tab}"; |
389
|
|
|
|
|
|
|
} |
390
|
287
|
100
|
|
|
|
783
|
unless (keys %tabs) { |
391
|
15
|
100
|
100
|
|
|
93
|
if ($operation eq "select" && $S->{returns}) { |
392
|
12
|
100
|
66
|
|
|
52
|
if ($args{flavor} && $args{flavor} eq "oracle") { |
393
|
3
|
|
|
|
|
9
|
$tabs{dual} = "dual"; |
394
|
|
|
|
|
|
|
} else { |
395
|
9
|
|
|
|
|
16
|
$next_bit = " "; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
} else { |
398
|
3
|
|
|
|
|
42
|
die "no tables specified in $operation\n"; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
} |
401
|
284
|
|
|
|
|
455
|
$sql .= $next_bit; |
402
|
284
|
|
|
|
|
374
|
my %seentab; |
403
|
284
|
|
|
|
|
447
|
my $joins = ""; |
404
|
284
|
|
|
|
|
380
|
for my $j ( @{$S->{joins}} ) { |
|
284
|
|
|
|
|
604
|
|
405
|
25
|
|
|
|
|
62
|
my ($join, $tab1, $tab2, $condition) = @$j; |
406
|
25
|
100
|
|
|
|
81
|
$condition = ( defined $condition) ? " on $condition" : ''; |
407
|
|
|
|
|
|
|
die "not sure what to do with repeated tables ($tabs{$tab1} and $tabs{$tab2}) in a join\n" |
408
|
25
|
100
|
100
|
|
|
134
|
if $seentab{$tab1} && $seentab{$tab2}; |
409
|
24
|
100
|
|
|
|
55
|
if ($seentab{$tab2}) { |
410
|
2
|
|
|
|
|
8
|
($tab1, $tab2) = ($tab2, $tab1); |
411
|
2
|
100
|
|
|
|
22
|
if ($join eq "left outer") { |
|
|
50
|
|
|
|
|
|
412
|
1
|
|
|
|
|
2
|
$join = "right outer"; |
413
|
|
|
|
|
|
|
} elsif ($join eq "right outer") { |
414
|
0
|
|
|
|
|
0
|
$join = "left outer"; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
} |
417
|
24
|
100
|
|
|
|
56
|
if ($seentab{$tab1}) { |
418
|
5
|
50
|
|
|
|
12
|
$joins .= " " if $joins; |
419
|
5
|
|
|
|
|
42
|
$joins .= "$join join $tabs{$tab2}$condition"; |
420
|
|
|
|
|
|
|
} else { |
421
|
19
|
100
|
|
|
|
34
|
$joins .= ", " if $joins; |
422
|
19
|
|
|
|
|
72
|
$joins .= "$tabs{$tab1} $join join $tabs{$tab2}$condition"; |
423
|
|
|
|
|
|
|
} |
424
|
24
|
|
|
|
|
46
|
$seentab{$tab1}++; |
425
|
24
|
|
|
|
|
44
|
$seentab{$tab2}++; |
426
|
|
|
|
|
|
|
} |
427
|
283
|
100
|
|
|
|
667
|
my @joins = $joins ? ($joins) : (); |
428
|
283
|
|
|
|
|
906
|
$sql .= join ", ", @joins, map { $tabs{$_} } grep { !$seentab{$_} } sort keys %tabs; |
|
281
|
|
|
|
|
860
|
|
|
321
|
|
|
|
|
949
|
|
429
|
|
|
|
|
|
|
|
430
|
283
|
|
|
|
|
500
|
my @sets = grep { $_ ne "" } @{$S->{sets}}; |
|
30
|
|
|
|
|
93
|
|
|
283
|
|
|
|
|
590
|
|
431
|
283
|
|
|
|
|
416
|
my @where = grep { $_ ne "" } @{$S->{where}}; |
|
188
|
|
|
|
|
485
|
|
|
283
|
|
|
|
|
488
|
|
432
|
283
|
|
|
|
|
396
|
my @having = grep { $_ ne "" } @{$S->{having}}; |
|
1
|
|
|
|
|
4
|
|
|
283
|
|
|
|
|
601
|
|
433
|
283
|
|
|
|
|
404
|
my @group_by = grep { $_ ne "" } @{$S->{group_by}}; |
|
3
|
|
|
|
|
18
|
|
|
283
|
|
|
|
|
515
|
|
434
|
283
|
|
|
|
|
362
|
my @order_by = grep { $_ ne "" } @{$S->{order_by}}; |
|
10
|
|
|
|
|
27
|
|
|
283
|
|
|
|
|
472
|
|
435
|
|
|
|
|
|
|
|
436
|
283
|
100
|
100
|
|
|
811
|
if ($S->{autogroup_needed} && !$S->{no_autogroup} && |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
437
|
3
|
|
|
|
|
22
|
!@group_by && @{$S->{autogroup_by}}) |
438
|
|
|
|
|
|
|
{ |
439
|
2
|
|
|
|
|
4
|
@group_by = grep { $_ ne "" } @{$S->{autogroup_by}}; |
|
3
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
6
|
|
440
|
|
|
|
|
|
|
} |
441
|
283
|
100
|
100
|
|
|
801
|
die "nothing to update\n" if $operation eq "update" && !@sets; |
442
|
|
|
|
|
|
|
|
443
|
282
|
100
|
|
|
|
741
|
$sql .= " set " . join ", ", @sets if @sets; |
444
|
282
|
100
|
|
|
|
857
|
$sql .= " where " . join " and ", @where if @where; |
445
|
282
|
100
|
|
|
|
621
|
$sql .= " group by " . join ", ", @group_by if @group_by; |
446
|
282
|
100
|
|
|
|
524
|
$sql .= " having " . join " and ", @having if @having; |
447
|
282
|
100
|
|
|
|
513
|
$sql .= " order by " . join ", ", @order_by if @order_by; |
448
|
|
|
|
|
|
|
|
449
|
282
|
100
|
100
|
|
|
694
|
if ($dangerous && !@where && !$S->{seen_exec}) { |
|
|
|
100
|
|
|
|
|
450
|
2
|
|
|
|
|
33
|
die "unfiltered $operation is dangerous: use exec if you want it\n"; |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
280
|
|
66
|
|
|
1092
|
my $use_rownum = $args{flavor} && $args{flavor} eq "oracle"; |
454
|
|
|
|
|
|
|
|
455
|
280
|
100
|
|
|
|
607
|
unless ($use_rownum) { |
456
|
268
|
100
|
|
|
|
575
|
if ($S->{limit}) { |
457
|
6
|
|
|
|
|
17
|
$sql .= " limit $S->{limit}"; |
458
|
|
|
|
|
|
|
} |
459
|
268
|
100
|
|
|
|
526
|
if ($S->{offset}) { |
460
|
4
|
|
|
|
|
12
|
$sql .= " offset $S->{offset}"; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
} |
463
|
280
|
|
|
|
|
472
|
my $v = $S->{set_values}; |
464
|
280
|
|
|
|
|
492
|
push @$v, @{$S->{ret_values}}; |
|
280
|
|
|
|
|
520
|
|
465
|
280
|
|
|
|
|
405
|
push @$v, @{$S->{join_values}}; |
|
280
|
|
|
|
|
402
|
|
466
|
280
|
|
|
|
|
396
|
push @$v, @{$S->{values}}; |
|
280
|
|
|
|
|
476
|
|
467
|
|
|
|
|
|
|
|
468
|
280
|
|
|
|
|
414
|
for my $add (@{$S->{additions}}) { |
|
280
|
|
|
|
|
601
|
|
469
|
8
|
|
|
|
|
33
|
$sql .= " $add->{type} $add->{sql}"; |
470
|
8
|
|
|
|
|
13
|
push @$v, @{$add->{vals}}; |
|
8
|
|
|
|
|
16
|
|
471
|
|
|
|
|
|
|
} |
472
|
280
|
|
|
|
|
1523
|
$sql =~ s/\s+$//; |
473
|
|
|
|
|
|
|
|
474
|
280
|
100
|
66
|
|
|
663
|
if ( $use_rownum && ( $S->{limit} || $S->{offset} )) { |
|
|
|
66
|
|
|
|
|
475
|
2
|
|
|
|
|
10
|
my @p; |
476
|
2
|
100
|
|
|
|
14
|
push @p, "ROWNUM > " . $S->{offset} if $S->{offset}; |
477
|
2
|
50
|
100
|
|
|
12
|
push @p, "ROWNUM <= " . ($S->{limit} + ($S->{offset} // 0)) if $S->{limit}; |
478
|
2
|
|
|
|
|
12
|
$sql = "select * from ($sql) where " . join(' and ', @p); |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
280
|
|
|
|
|
4245
|
return ($sql, $v, $nret, %flags); |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
1; |
486
|
|
|
|
|
|
|
__END__ |