line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DBIx::Array; |
2
|
13
|
|
|
13
|
|
1478592
|
use strict; |
|
13
|
|
|
|
|
171
|
|
|
13
|
|
|
|
|
396
|
|
3
|
13
|
|
|
13
|
|
67
|
use warnings; |
|
13
|
|
|
|
|
35
|
|
|
13
|
|
|
|
|
399
|
|
4
|
13
|
|
|
13
|
|
101
|
use File::Basename qw{basename}; |
|
13
|
|
|
|
|
37
|
|
|
13
|
|
|
|
|
1400
|
|
5
|
13
|
|
|
13
|
|
6889
|
use Tie::Cache; |
|
13
|
|
|
|
|
41967
|
|
|
13
|
|
|
|
|
472
|
|
6
|
13
|
|
|
13
|
|
8138
|
use Data::Dumper qw{Dumper}; |
|
13
|
|
|
|
|
93223
|
|
|
13
|
|
|
|
|
1057
|
|
7
|
13
|
|
|
13
|
|
115
|
use List::Util qw(sum); |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
849
|
|
8
|
13
|
|
|
13
|
|
23914
|
use DBI; |
|
13
|
|
|
|
|
250769
|
|
|
13
|
|
|
|
|
832
|
|
9
|
13
|
|
|
13
|
|
6278
|
use DBIx::Array::Session::Action; |
|
13
|
|
|
|
|
36
|
|
|
13
|
|
|
|
|
69874
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.65'; |
12
|
|
|
|
|
|
|
our $PACKAGE = __PACKAGE__; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
DBIx::Array - DBI Wrapper with Perl style data structure interfaces |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 SYNOPSIS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use DBIx::Array; |
21
|
|
|
|
|
|
|
my $dbx = DBIx::Array->new; |
22
|
|
|
|
|
|
|
$dbx->connect($connection, $user, $pass, \%opt); #passed to DBI |
23
|
|
|
|
|
|
|
my @array = $dbx->sqlarray($sql, @params); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
With a connected database handle |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
use DBIx::Array; |
28
|
|
|
|
|
|
|
my $dbx = DBIx::Array->new(dbh=>$dbh); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
With stored connection information from a File |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
use DBIx::Array::Connect; |
33
|
|
|
|
|
|
|
my $dbx = DBIx::Array::Connect->new(file=>"my.ini")->connect("mydatabase"); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 DESCRIPTION |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
This module provides a Perl data structure interface for Structured Query Language (SQL). This module is for people who truly understand SQL and who understand Perl data structures. If you understand how to modify your SQL to meet your data requirements then this module is for you. |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
This module is used to connect to Oracle 10g and 11g using L on both Linux and Win32, MySQL 4 and 5 using L on Linux, Microsoft SQL Server using L on Linux and using L on Win32 systems, and PostgreSQL using L in a 24x7 production environment. Tests are written against L and L. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head2 CONVENTIONS |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=over |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=item Methods are named "type + data structure". |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=over |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item sql - Methods that are type "sql" use the passed SQL to hit the database. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=item abs - Methods that are type "abs" use L to build the SQL to hit the database. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=item sqlwhere - Methods that are type "sqlwhere" use the passed SQL appended with the passed where structure with L->where to build the SQL to hit the database. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=back |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=item Methods data structures are: |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=over |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=item scalar - which is a single value the value from the first column of the first row. |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=item array - which is a flattened list of values from all columns from all rows. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=item hash - which is the first two columns of values as a hash or hash reference |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=item arrayarray - which is an array of array references (i.e. data table) |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=item arrayhash - which is an array of hash references (works best when used with case sensitive column aliases) |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=item hashhash - which is a hash where the keys are the values of the first column and the values are a hash reference of all (including the key) column values. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=item arrayarrayname - which is an array of array references (i.e. data table) with the first row being the column names passed from the database |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item arrayhashname - which is an array of hash references with the first row being the column names passed from the database |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=item arrayobject - which is an array of hash references blessed into the passed class namespace |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=back |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=item Methods are context sensitive |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=over |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=item Methods in list context return a list e.g. (), ([],[],[],...), ({},{},{},...) |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=item Methods in scalar context return an array reference e.g. [], [[],[],[],...], [{},{},{},...] |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=back |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=back |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=head1 USAGE |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Loop through data |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
foreach my $row ($dbx->sqlarrayhash($sql, @bind)) { |
98
|
|
|
|
|
|
|
do_something($row->{"id"}, $row->{"column"}); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Easily generate an HTML table |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
my $cgi = CGI->new(""); |
104
|
|
|
|
|
|
|
my $html = $cgi->table($cgi->Tr([map {$cgi->td($_)} $dbx->sqlarrayarrayname($sql, @param)])); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Bless directly into a class |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
my ($object) = $dbx->sqlarrayobject("My::Package", $sql, {id=>$id}); #bless({id=>1, name=>'foo'}, 'My::Package'); |
109
|
|
|
|
|
|
|
my @objects = $dbx->absarrayobject("My::Package", "myview", '*', {active=>1}, ["name"]); #($object, $object, ...) |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head2 new |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my $dbx = DBIx::Array->new(); |
116
|
|
|
|
|
|
|
$dbx->connect(...); #connect to database, sets and returns dbh |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
my $dbx = DBIx::Array->new(dbh=>$dbh); #already have a handle |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=cut |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub new { |
123
|
21
|
|
|
21
|
1
|
768630
|
my $this = shift; |
124
|
21
|
100
|
|
|
|
97
|
my $class = ref($this) ? ref($this) : $this; |
125
|
21
|
|
|
|
|
50
|
my $self = {}; |
126
|
21
|
|
|
|
|
77
|
bless $self, $class; |
127
|
21
|
|
|
|
|
101
|
$self->initialize(@_); |
128
|
21
|
|
|
|
|
60
|
return $self; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head2 initialize |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=cut |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub initialize { |
136
|
21
|
|
|
21
|
1
|
46
|
my $self = shift; |
137
|
21
|
|
|
|
|
90
|
%$self = @_; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head1 METHODS (Properties) |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 dbh |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Sets or returns the database handle object. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
my $dbh = $dbx->dbh; |
147
|
|
|
|
|
|
|
$dbx->dbh($dbh); #if you already have a connection |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub dbh { |
152
|
39
|
|
|
39
|
1
|
23818
|
my $self = shift; |
153
|
39
|
100
|
|
|
|
113
|
if (@_) { |
154
|
5
|
|
|
|
|
14
|
CORE::delete $self->{'_prepared'}; #clear cache if we switch handles |
155
|
5
|
|
|
|
|
15
|
$self->{'dbh'} = shift; |
156
|
|
|
|
|
|
|
} |
157
|
39
|
|
|
|
|
334
|
return $self->{'dbh'}; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 name |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Sets or returns a user friendly identification string for this database connection |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
my $name = $dbx->name; |
165
|
|
|
|
|
|
|
$dbx->name($string); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub name { |
170
|
4
|
|
|
4
|
1
|
1480
|
my $self = shift; |
171
|
4
|
100
|
|
|
|
14
|
$self->{'name'} = shift if @_; |
172
|
4
|
|
|
|
|
19
|
return $self->{'name'}; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head1 METHODS (DBI Wrappers) |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 connect |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Wrapper around DBI->connect; Connects to the database, sets dbh property, and returns the database handle. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
$dbx->connect($connection, $user, $pass, \%opt); #sets $dbx->dbh |
182
|
|
|
|
|
|
|
my $dbh = $dbx->connect($connection, $user, $pass, \%opt); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Examples: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
$dbx->connect("DBI:mysql:database=mydb;host=myhost", "user", "pass", {AutoCommit=>1, RaiseError=>1}); |
187
|
|
|
|
|
|
|
$dbx->connect("DBI:Sybase:server=myhost;datasbase=mydb", "user", "pass", {AutoCommit=>1, RaiseError=>1}); #Microsoft SQL Server API is same as Sybase API |
188
|
|
|
|
|
|
|
$dbx->connect("DBI:Oracle:TNSNAME", "user", "pass", {AutoCommit=>1, RaiseError=>1}); |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=cut |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub connect { |
193
|
5
|
|
|
5
|
1
|
1077262
|
my $self = shift; |
194
|
5
|
|
|
|
|
531
|
local $0 = sprintf("perl:%s", basename($0)); #Force DBD::Oracle to show "perl:script@host" in v$session.program instead of "perl@host" |
195
|
5
|
|
|
|
|
75
|
my $dbh = DBI->connect(@_); |
196
|
5
|
|
|
|
|
13587
|
$self->dbh($dbh); |
197
|
5
|
50
|
|
|
|
53
|
CORE::delete $self->{'action'} if exists $self->{'action'}; |
198
|
5
|
|
|
|
|
98
|
tie $self->{'action'}, "DBIx::Array::Session::Action", (parent=>$self); |
199
|
5
|
|
|
|
|
28
|
return $self->dbh; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head2 disconnect |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Wrapper around dbh->disconnect |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
$dbx->disconnect; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=cut |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub disconnect { |
211
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
212
|
0
|
|
|
|
|
0
|
untie $self->{'action'}; |
213
|
0
|
|
|
|
|
0
|
CORE::delete $self->{'action'}; |
214
|
0
|
|
|
|
|
0
|
return $self->dbh->disconnect |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head2 commit |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Wrapper around dbh->commit |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
$dbx->commit; |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=cut |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub commit { |
226
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
227
|
0
|
|
|
|
|
0
|
local $self->dbh->{'AutoCommit'} = 0; |
228
|
0
|
|
|
|
|
0
|
return $self->dbh->commit; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=head2 rollback |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Wrapper around dbh->rollback |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
$dbx->rollback; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=cut |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
sub rollback { |
240
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
241
|
0
|
|
|
|
|
0
|
return $self->dbh->rollback; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head2 prepare |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Wrapper around dbh->prepare with a L cache. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
my $sth = $dbx->prepare($sql); |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=cut |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub prepare { |
253
|
49
|
|
|
49
|
1
|
75
|
my $self = shift; |
254
|
49
|
|
|
|
|
71
|
my $sql = shift; |
255
|
49
|
|
|
|
|
75
|
my $sth; |
256
|
49
|
50
|
|
|
|
116
|
if ($self->prepare_max_count > 0) { |
257
|
49
|
|
66
|
|
|
140
|
my $cache = $self->{'_prepared'} ||= $self->_prepare_tie; #orisahash |
258
|
49
|
|
66
|
|
|
272
|
$sth = $cache->{$sql} ||= $self->dbh->prepare($sql); #orisacache |
259
|
|
|
|
|
|
|
} else { |
260
|
0
|
|
|
|
|
0
|
$sth = $self->dbh->prepare($sql); |
261
|
|
|
|
|
|
|
} |
262
|
49
|
50
|
|
|
|
40292
|
die($self->errstr) unless $sth; |
263
|
49
|
|
|
|
|
128
|
return $sth; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
sub _prepare_tie { |
267
|
6
|
|
|
6
|
|
13
|
my $self = shift; |
268
|
6
|
|
|
|
|
16
|
my $hash = {}; |
269
|
6
|
|
|
|
|
21
|
tie %$hash, 'Tie::Cache', {MaxCount => $self->prepare_max_count}; |
270
|
6
|
|
|
|
|
300
|
return $hash; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head2 prepare_max_count |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
Maximum number of prepared statements to keep in the cache. |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
$dbx->prepare_max_count(128); #default |
278
|
|
|
|
|
|
|
$dbx->prepare_max_count(0); #disabled |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=cut |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub prepare_max_count { |
283
|
58
|
|
|
58
|
1
|
93
|
my $self = shift; |
284
|
58
|
100
|
|
|
|
146
|
if (@_) { |
285
|
1
|
|
|
|
|
4
|
$self->{"prepare_max_count"} = shift; |
286
|
1
|
|
|
|
|
2
|
CORE::delete $self->{'_prepared'}; #clear cache if we switch handles |
287
|
|
|
|
|
|
|
} |
288
|
58
|
100
|
|
|
|
174
|
$self->{"prepare_max_count"} = 128 unless defined $self->{"prepare_max_count"}; |
289
|
58
|
|
|
|
|
220
|
return $self->{"prepare_max_count"}; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=head2 AutoCommit |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
Wrapper around dbh->{'AutoCommit'} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
$dbx->AutoCommit(1); |
297
|
|
|
|
|
|
|
&doSomething if $dbx->AutoCommit; |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
For transactions that must complete together, I recommend |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
{ #block to keep local... well... local. |
302
|
|
|
|
|
|
|
local $dbx->dbh->{'AutoCommit'} = 0; |
303
|
|
|
|
|
|
|
$dbx->sqlinsert($sql1, @bind1); |
304
|
|
|
|
|
|
|
$dbx->sqlupdate($sql2, @bind2); |
305
|
|
|
|
|
|
|
$dbx->sqlinsert($sql3, @bind3); |
306
|
|
|
|
|
|
|
} #What is AutoCommit now? Do you care? |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
If AutoCommit reverts to true at the end of the block then DBI commits. Else AutoCommit is still false and still not committed. This allows higher layers to determine commit functionality. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=cut |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub AutoCommit { |
313
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
314
|
0
|
0
|
|
|
|
0
|
if (@_) { |
315
|
0
|
|
|
|
|
0
|
$self->dbh->{'AutoCommit'} = shift; |
316
|
|
|
|
|
|
|
} |
317
|
0
|
|
|
|
|
0
|
return $self->dbh->{'AutoCommit'}; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head2 RaiseError |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Wrapper around dbh->{'RaiseError'} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
$dbx->RaiseError(1); |
325
|
|
|
|
|
|
|
&doSomething if $dbx->RaiseError; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
{ #local block |
328
|
|
|
|
|
|
|
local $dbx->dbh->{'RaiseError'} = 0; |
329
|
|
|
|
|
|
|
$dbx->sqlinsert($sql, @bind); #do not die |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=cut |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub RaiseError { |
335
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
336
|
0
|
0
|
|
|
|
0
|
if (@_) { |
337
|
0
|
|
|
|
|
0
|
$self->dbh->{'RaiseError'} = shift; |
338
|
|
|
|
|
|
|
} |
339
|
0
|
|
|
|
|
0
|
return $self->dbh->{'RaiseError'}; |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=head2 errstr |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
Wrapper around $DBI::errstr |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
my $err = $dbx->errstr; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=cut |
349
|
|
|
|
|
|
|
|
350
|
0
|
|
|
0
|
1
|
0
|
sub errstr {$DBI::errstr}; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=head1 METHODS (Read) - SQL |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=head2 sqlcursor |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
Returns the prepared and executed SQL cursor so that you can use the cursor elsewhere. Every method in this package uses this single method to generate a sqlcursor. |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
my $sth = $dbx->sqlcursor($sql, @param); #binds are ? values are positional |
359
|
|
|
|
|
|
|
my $sth = $dbx->sqlcursor($sql, \@param); #binds are ? values are positional |
360
|
|
|
|
|
|
|
my $sth = $dbx->sqlcursor($sql, \%param); #binds are :key |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
Note: In true Perl fashion extra hash binds are ignored. |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
my @foo = $dbx->sqlarray("select :foo, :bar from dual", |
365
|
|
|
|
|
|
|
{foo=>"a", bar=>1, baz=>"buz"}); #returns ("a", 1) |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
my $one = $dbx->sqlscalar("select ? from dual", ["one"]); #returns "one" |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
my $two = $dbx->sqlscalar("select ? from dual", "two"); #returns "two" |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Scalar references are passed in and out with a hash bind. |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
my $inout = 3; |
374
|
|
|
|
|
|
|
$dbx->sqlexecute("BEGIN :inout := :inout * 2; END;", {inout=>\$inout}); |
375
|
|
|
|
|
|
|
print "$inout\n"; #$inout is 6 |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Direct Plug-in for L but no column alias support. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
my $sabs = SQL::Abstract->new; |
380
|
|
|
|
|
|
|
my $sth = $dbx->sqlcursor($sabs->select($table, \@columns, \%where, \@sort)); |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=cut |
383
|
|
|
|
|
|
|
|
384
|
0
|
|
|
|
|
0
|
sub sqlcursor { |
385
|
49
|
|
|
49
|
1
|
821
|
my $self = shift; |
386
|
49
|
|
|
|
|
80
|
my $sql = shift; |
387
|
49
|
|
|
|
|
149
|
my $sth = $self->prepare($sql); |
388
|
49
|
100
|
|
|
|
164
|
if (ref($_[0]) eq "ARRAY") { |
|
|
50
|
|
|
|
|
|
389
|
2
|
|
|
|
|
9
|
my $bind_aref = shift; |
390
|
2
|
50
|
|
|
|
18
|
$sth->execute(@$bind_aref) or die(&_error_string($self->errstr, $sql, sprintf("[%s]", join(", ", @$bind_aref)), "Array Reference")); |
391
|
|
|
|
|
|
|
} elsif (ref($_[0]) eq "HASH") { |
392
|
0
|
|
|
|
|
0
|
my $bind_href = shift; |
393
|
0
|
|
|
|
|
0
|
foreach my $key (keys %$bind_href) { |
394
|
0
|
0
|
|
|
|
0
|
next unless $sql =~ m/:$key\b/; #TODO: comments are scanned so /* :foo */ is not supported here |
395
|
0
|
0
|
|
|
|
0
|
if (ref($bind_href->{$key}) eq "SCALAR") { |
396
|
0
|
|
|
|
|
0
|
$sth->bind_param_inout(":$key" => $bind_href->{$key}, 255); |
397
|
|
|
|
|
|
|
} else { |
398
|
0
|
|
|
|
|
0
|
$sth->bind_param(":$key" => $bind_href->{$key}); |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
} |
401
|
0
|
0
|
|
|
|
0
|
$sth->execute or die(&_error_string($self->errstr, $sql, sprintf("{%s}", join(", ", map {join("=>", $_ => $bind_href->{$_})} sort keys %$bind_href)), "Hash Reference")); |
|
0
|
|
|
|
|
0
|
|
402
|
|
|
|
|
|
|
} else { |
403
|
47
|
|
|
|
|
103
|
my @bind = @_; |
404
|
47
|
50
|
|
|
|
292
|
$sth->execute(@bind) or die(&_error_string($self->errstr, $sql, sprintf("(%s)", join(", ", @bind)), "List")); |
405
|
|
|
|
|
|
|
} |
406
|
49
|
|
|
|
|
84187
|
return $sth; |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub _error_string { |
409
|
0
|
|
|
0
|
|
0
|
my $err = shift; |
410
|
0
|
|
|
|
|
0
|
my $sql = shift; |
411
|
0
|
|
|
|
|
0
|
my $bind_str = shift; |
412
|
0
|
|
|
|
|
0
|
my $type = shift; |
413
|
0
|
0
|
|
|
|
0
|
if ($bind_str) { |
414
|
0
|
|
|
|
|
0
|
return sprintf("Database Execute Error: %s\nSQL: %s\nBind(%s): %s\n", $err, $sql, $type, $bind_str); |
415
|
|
|
|
|
|
|
} else { |
416
|
0
|
|
|
|
|
0
|
return sprintf("Database Prepare Error: %s\nSQL: %s\n", $err, $sql); |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=head2 sqlscalar |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Returns the first row first column value as a scalar. |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
This works great for selecting one value. |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
my $scalar = $dbx->sqlscalar($sql, @parameters); #returns $ |
428
|
|
|
|
|
|
|
my $scalar = $dbx->sqlscalar($sql, \@parameters); #returns $ |
429
|
|
|
|
|
|
|
my $scalar = $dbx->sqlscalar($sql, \%parameters); #returns $ |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub sqlscalar { |
434
|
8
|
|
|
8
|
1
|
885
|
my $self = shift; |
435
|
8
|
|
|
|
|
49
|
my @data = $self->sqlarray(@_); |
436
|
8
|
|
|
|
|
67
|
return $data[0]; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=head2 sqlarray |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
Returns the SQL result as an array or array reference. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
This works great for selecting one column from a table or selecting one row from a table. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
my $array = $dbx->sqlarray($sql, @parameters); #returns [$,$,$,...] |
446
|
|
|
|
|
|
|
my @array = $dbx->sqlarray($sql, @parameters); #returns ($,$,$,...) |
447
|
|
|
|
|
|
|
my $array = $dbx->sqlarray($sql, \@parameters); #returns [$,$,$,...] |
448
|
|
|
|
|
|
|
my @array = $dbx->sqlarray($sql, \@parameters); #returns ($,$,$,...) |
449
|
|
|
|
|
|
|
my $array = $dbx->sqlarray($sql, \%parameters); #returns [$,$,$,...] |
450
|
|
|
|
|
|
|
my @array = $dbx->sqlarray($sql, \%parameters); #returns ($,$,$,...) |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
=cut |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
sub sqlarray { |
455
|
15
|
|
|
15
|
1
|
6859
|
my $self = shift; |
456
|
15
|
|
|
|
|
52
|
my $rows = $self->sqlarrayarray(@_); |
457
|
15
|
|
|
|
|
45
|
my @rows = map {@$_} @$rows; |
|
19
|
|
|
|
|
56
|
|
458
|
15
|
100
|
|
|
|
70
|
return wantarray ? @rows : \@rows; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=head2 sqlhash |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
Returns the first two columns of the SQL result as a hash or hash reference {Key=>Value, Key=>Value, ...} |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
my $hash = $dbx->sqlhash($sql, @parameters); #returns {$=>$, $=>$, ...} |
466
|
|
|
|
|
|
|
my %hash = $dbx->sqlhash($sql, @parameters); #returns ($=>$, $=>$, ...) |
467
|
|
|
|
|
|
|
my @hash = $dbx->sqlhash($sql, @parameters); #this is ordered |
468
|
|
|
|
|
|
|
my @keys = grep {!($n++ % 2)} @hash; #ordered keys |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
my $hash = $dbx->sqlhash($sql, \@parameters); #returns {$=>$, $=>$, ...} |
471
|
|
|
|
|
|
|
my %hash = $dbx->sqlhash($sql, \@parameters); #returns ($=>$, $=>$, ...) |
472
|
|
|
|
|
|
|
my $hash = $dbx->sqlhash($sql, \%parameters); #returns {$=>$, $=>$, ...} |
473
|
|
|
|
|
|
|
my %hash = $dbx->sqlhash($sql, \%parameters); #returns ($=>$, $=>$, ...) |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=cut |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
sub sqlhash { |
478
|
2
|
|
|
2
|
1
|
10335
|
my $self = shift; |
479
|
2
|
|
|
|
|
19
|
my @rows = map {$_->[0], $_->[1]} $self->sqlarrayarray(@_); |
|
6
|
|
|
|
|
18
|
|
480
|
2
|
100
|
|
|
|
18
|
return wantarray ? @rows : {@rows}; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
=head2 sqlhashhash |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
Returns a hash where the keys are the values of the first column and the values are a hash reference of all (including the key) column values. |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
my $hash = $dbx->sqlhashhash($sql, @parameters); #returns {$=>{}, $=>{}, ...} |
488
|
|
|
|
|
|
|
my %hash = $dbx->sqlhashhash($sql, @parameters); #returns ($=>{}, $=>{}, ...) |
489
|
|
|
|
|
|
|
my @hash = $dbx->sqlhashhash($sql, @parameters); #returns ($=>{}, $=>{}, ...) #ordered |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=cut |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
sub sqlhashhash { |
494
|
2
|
|
|
2
|
1
|
8195
|
my $self = shift; |
495
|
2
|
|
|
|
|
10
|
my $rows = $self->sqlarrayhashname(@_); |
496
|
2
|
|
|
|
|
10
|
my $header = shift @$rows; |
497
|
2
|
|
|
|
|
5
|
my $column = shift @$header; |
498
|
2
|
|
|
|
|
4
|
my @rows = map {$_->{$column} => $_} @$rows; |
|
6
|
|
|
|
|
15
|
|
499
|
2
|
100
|
|
|
|
26
|
return wantarray ? @rows : {@rows}; |
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
=head2 sqlarrayarray |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of array references ([],[],...) or [[],[],...] |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayarray($sql, @parameters); #returns [[$,$,...],[],[],...] |
507
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayarray($sql, @parameters); #returns ([$,$,...],[],[],...) |
508
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayarray($sql, \@parameters); #returns [[$,$,...],[],[],...] |
509
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayarray($sql, \@parameters); #returns ([$,$,...],[],[],...) |
510
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayarray($sql, \%parameters); #returns [[$,$,...],[],[],...] |
511
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayarray($sql, \%parameters); #returns ([$,$,...],[],[],...) |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=cut |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
sub sqlarrayarray { |
516
|
19
|
|
|
19
|
1
|
9518
|
my $self = shift; |
517
|
19
|
|
|
|
|
43
|
my $sql = shift; |
518
|
19
|
|
|
|
|
80
|
return $self->_sqlarrayarray(sql=>$sql, param=>[@_], name=>0); |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=head2 sqlarrayarrayname |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of array references ([],[],...) or [[],[],...] where the first row contains an array reference to the column names |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayarrayname($sql, @parameters); #returns [[$,$,...],[]...] |
526
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayarrayname($sql, @parameters); #returns ([$,$,...],[]...) |
527
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayarrayname($sql, \@parameters); #returns [[$,$,...],[]...] |
528
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayarrayname($sql, \@parameters); #returns ([$,$,...],[]...) |
529
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayarrayname($sql, \%parameters); #returns [[$,$,...],[]...] |
530
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayarrayname($sql, \%parameters); #returns ([$,$,...],[]...) |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
Create an HTML table with L |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
my $cgi = CGI->new; |
535
|
|
|
|
|
|
|
my $html = $cgi->table($cgi->Tr([map {$cgi->td($_)} $dbx->sqlarrayarrayname($sql, @param)])); |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=cut |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
sub sqlarrayarrayname { |
540
|
2
|
|
|
2
|
1
|
17074
|
my $self = shift; |
541
|
2
|
|
|
|
|
6
|
my $sql = shift; |
542
|
2
|
|
|
|
|
8
|
return $self->_sqlarrayarray(sql=>$sql, param=>[@_], name=>1); |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
# _sqlarrayarray |
546
|
|
|
|
|
|
|
# |
547
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayarray(sql=>$sql, param=>[ @parameters], name=>1); |
548
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayarray(sql=>$sql, param=>[ @parameters], name=>1); |
549
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayarray(sql=>$sql, param=>[ @parameters], name=>0); |
550
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayarray(sql=>$sql, param=>[ @parameters], name=>0); |
551
|
|
|
|
|
|
|
# |
552
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\@parameters], name=>1); |
553
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\@parameters], name=>1); |
554
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\@parameters], name=>0); |
555
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\@parameters], name=>0); |
556
|
|
|
|
|
|
|
# |
557
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\%parameters], name=>1); |
558
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\%parameters], name=>1); |
559
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\%parameters], name=>0); |
560
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayarray(sql=>$sql, param=>[\%parameters], name=>0); |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
sub _sqlarrayarray { |
563
|
21
|
|
|
21
|
|
34
|
my $self = shift; |
564
|
21
|
|
|
|
|
78
|
my %data = @_; |
565
|
21
|
50
|
|
|
|
50
|
my $sth = $self->sqlcursor($data{'sql'}, @{$data{'param'}}) or die($self->errstr); |
|
21
|
|
|
|
|
62
|
|
566
|
21
|
|
|
|
|
187
|
my $name = $sth->{'NAME'}; #DBD::mysql must store this first |
567
|
21
|
|
|
|
|
815
|
my @rows = (); |
568
|
|
|
|
|
|
|
#TODO: replace with fetchall_arrayref |
569
|
21
|
|
|
|
|
124
|
while (my $row = $sth->fetchrow_arrayref()) { |
570
|
37
|
|
|
|
|
1404
|
push @rows, [@$row]; |
571
|
|
|
|
|
|
|
} |
572
|
21
|
100
|
|
|
|
462
|
unshift @rows, $name if $data{'name'}; |
573
|
21
|
|
|
|
|
76
|
$sth->finish; |
574
|
21
|
100
|
|
|
|
222
|
return wantarray ? @rows : \@rows; |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=head2 sqlarrayhash |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of hash references ({},{},...) or [{},{},...] |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayhash($sql, @parameters); #returns [{},{},{},...] |
582
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayhash($sql, @parameters); #returns ({},{},{},...) |
583
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayhash($sql, \@parameters); #returns [{},{},{},...] |
584
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayhash($sql, \@parameters); #returns ({},{},{},...) |
585
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayhash($sql, \%parameters); #returns [{},{},{},...] |
586
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayhash($sql, \%parameters); #returns ({},{},{},...) |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
This method is best used to select a list of hashes out of the database to bless directly into a package. |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
my $sql = q{SELECT COL1 AS "id", COL2 AS "name" FROM TABLE1}; |
591
|
|
|
|
|
|
|
my @objects = map {bless $_, MyPackage} $dbx->sqlarrayhash($sql, @parameters); |
592
|
|
|
|
|
|
|
my @objects = map {MyPackage->new(%$_)} $dbx->sqlarrayhash($sql, @parameters); |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
The @objects array is now a list of blessed MyPackage objects. |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=cut |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub sqlarrayhash { |
599
|
4
|
|
|
4
|
1
|
17040
|
my $self = shift; |
600
|
4
|
|
|
|
|
10
|
my $sql = shift; |
601
|
4
|
|
|
|
|
18
|
return $self->_sqlarrayhash(sql=>$sql, param=>[@_], name=>0); |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
=head2 sqlarrayhashname |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of hash references ([],{},{},...) or [[],{},{},...] where the first row contains an array reference to the column names |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayhashname($sql, @parameters); #returns [[],{},{},...] |
609
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayhashname($sql, @parameters); #returns ([],{},{},...) |
610
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayhashname($sql, \@parameters); #returns [[],{},{},...] |
611
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayhashname($sql, \@parameters); #returns ([],{},{},...) |
612
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayhashname($sql, \%parameters); #returns [[],{},{},...] |
613
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayhashname($sql, \%parameters); #returns ([],{},{},...) |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=cut |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
sub sqlarrayhashname { |
618
|
4
|
|
|
4
|
1
|
16965
|
my $self = shift; |
619
|
4
|
|
|
|
|
18
|
my $sql = shift; |
620
|
4
|
|
|
|
|
27
|
return $self->_sqlarrayhash(sql=>$sql, param=>[@_], name=>1); |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# _sqlarrayhash |
624
|
|
|
|
|
|
|
# |
625
|
|
|
|
|
|
|
# Returns the SQL result as an array or array ref of hash references ({},{},...) or [{},{},...] |
626
|
|
|
|
|
|
|
# |
627
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayhash(sql=>$sql, param=>\@parameters, name=>1); |
628
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayhash(sql=>$sql, param=>\@parameters, name=>1); |
629
|
|
|
|
|
|
|
# my $array = $dbx->_sqlarrayhash(sql=>$sql, param=>\@parameters, name=>0); |
630
|
|
|
|
|
|
|
# my @array = $dbx->_sqlarrayhash(sql=>$sql, param=>\@parameters, name=>0); |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
sub _sqlarrayhash { |
633
|
8
|
|
|
8
|
|
16
|
my $self = shift; |
634
|
8
|
|
|
|
|
31
|
my %data = @_; |
635
|
8
|
50
|
|
|
|
18
|
my $sth = $self->sqlcursor($data{'sql'}, @{$data{'param'}}) or die($self->errstr); |
|
8
|
|
|
|
|
24
|
|
636
|
8
|
|
|
|
|
62
|
my $name = $sth->{'NAME'}; #DBD::mysql must store this first |
637
|
8
|
|
|
|
|
326
|
my @rows = (); |
638
|
8
|
|
|
|
|
72
|
while (my $row = $sth->fetchrow_hashref()) { |
639
|
24
|
|
|
|
|
2160
|
push @rows, {%$row}; |
640
|
|
|
|
|
|
|
} |
641
|
8
|
100
|
|
|
|
422
|
unshift @rows, $name if $data{'name'}; |
642
|
8
|
|
|
|
|
33
|
$sth->finish; |
643
|
8
|
100
|
|
|
|
121
|
return wantarray ? @rows : \@rows; |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
=head2 sqlarrayobject |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
Returns the SQL result as an array of blessed hash objects in to the $class namespace. |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
my $array = $dbx->sqlarrayobject($class, $sql, @parameters); #returns [bless({}, $class), ...] |
651
|
|
|
|
|
|
|
my @array = $dbx->sqlarrayobject($class, $sql, @parameters); #returns (bless({}, $class), ...) |
652
|
|
|
|
|
|
|
my ($object) = $dbx->sqlarrayobject($class, $sql, {id=>$id}); #$object is bless({}, $class) |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
=cut |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
sub sqlarrayobject { |
657
|
3
|
|
|
3
|
1
|
39686
|
my $self = shift; |
658
|
3
|
100
|
|
|
|
19
|
my $class = shift or die("Error: The sqlarrayobject method requires a class parameter"); |
659
|
2
|
|
|
|
|
9
|
my @objects = map {bless($_, $class)} $self->sqlarrayhash(@_); |
|
6
|
|
|
|
|
25
|
|
660
|
2
|
100
|
|
|
|
10
|
wantarray ? @objects : \@objects; |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
=head2 sqlsort (Oracle Specific?) |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
Returns the SQL statement with the correct ORDER BY clause given a SQL statement (without an ORDER BY clause) and a signed integer on which column to sort. |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
my $sql = $dbx->sqlsort(qq{SELECT 1,'Z' FROM DUAL UNION SELECT 2,'A' FROM DUAL}, -2); |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
Returns |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
SELECT 1,'Z' FROM DUAL UNION SELECT 2,'A' FROM DUAL ORDER BY 2 DESC |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
Note: The sqlsort method is no longer preferred. It is recommended to use the newer sqlwhere capability. |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
=cut |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
sub sqlsort { |
678
|
2
|
|
|
2
|
1
|
9577
|
my $self = shift; |
679
|
2
|
|
|
|
|
4
|
my $sql = shift; |
680
|
2
|
|
|
|
|
5
|
my $sort = int(shift); #not sure we need int here but I did not want to change behavior |
681
|
2
|
50
|
|
|
|
5
|
if (defined($sort)) { |
682
|
2
|
|
|
|
|
6
|
my $column = abs($sort); |
683
|
2
|
100
|
|
|
|
7
|
my $direction = $sort < 0 ? "DESC" : "ASC"; |
684
|
2
|
|
|
|
|
25
|
return join " ", $sql, sprintf("ORDER BY %u %s", $column, $direction); |
685
|
|
|
|
|
|
|
} else { |
686
|
0
|
|
|
|
|
0
|
return $sql; |
687
|
|
|
|
|
|
|
} |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
=head2 sqlarrayarraynamesort |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
Returns a sqlarrayarrayname for $sql sorted on column $n where n is an integer ascending for positive, descending for negative, and 0 for no sort. |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
my $data = $dbx->sqlarrayarraynamesort($sql, $n, @parameters); |
695
|
|
|
|
|
|
|
my $data = $dbx->sqlarrayarraynamesort($sql, $n, \@parameters); |
696
|
|
|
|
|
|
|
my $data = $dbx->sqlarrayarraynamesort($sql, $n, \%parameters); |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
Note: $sql must not have an "ORDER BY" clause in order for this function to work correctly. |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
Note: The sqlarrayarraynamesort method is no longer preferred. It is recommended to use the newer sqlwherearrayarrayname capability. |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
=cut |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
sub sqlarrayarraynamesort { |
705
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
706
|
0
|
|
|
|
|
0
|
my $sql = shift; |
707
|
0
|
|
|
|
|
0
|
my $sort = shift; |
708
|
0
|
|
|
|
|
0
|
return $self->sqlarrayarrayname($self->sqlsort($sql, $sort), @_); |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
=head1 METHODS (Read) - SQL::Abstract |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
Please note the "abs" API is a 100% pass through to L. Please reference the L documentation for syntax assistance with that API. |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
=head2 abscursor |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
Returns the prepared and executed SQL cursor. |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
my $sth = $dbx->abscursor($table, \@columns, \%where, \@order); |
720
|
|
|
|
|
|
|
my $sth = $dbx->abscursor($table, \@columns, \%where); #no order required defaults to storage |
721
|
|
|
|
|
|
|
my $sth = $dbx->abscursor($table, \@columns); #no where required defaults to all |
722
|
|
|
|
|
|
|
my $sth = $dbx->abscursor($table); #no columns required defaults to '*' (all) |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
=cut |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
sub abscursor { |
727
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
728
|
0
|
|
|
|
|
0
|
return $self->sqlcursor($self->abs->select(@_)); |
729
|
|
|
|
|
|
|
} |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
=head2 absscalar |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
Returns the first row first column value as a scalar. |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
This works great for selecting one value. |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
my $scalar = $dbx->absscalar($table, \@columns, \%where, \@order); #returns $ |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
=cut |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub absscalar { |
742
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
743
|
0
|
|
|
|
|
0
|
return $self->sqlscalar($self->abs->select(@_)); |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
=head2 absarray |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
Returns the SQL result as a array. |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
This works great for selecting one column from a table or selecting one row from a table. |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
my @array = $dbx->absarray($table, \@columns, \%where, \@order); #returns () |
753
|
|
|
|
|
|
|
my $array = $dbx->absarray($table, \@columns, \%where, \@order); #returns [] |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
=cut |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
sub absarray { |
758
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
759
|
0
|
|
|
|
|
0
|
return $self->sqlarray($self->abs->select(@_)); |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
=head2 abshash |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
Returns the first two columns of the SQL result as a hash or hash reference {Key=>Value, Key=>Value, ...} |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
my $hash = $dbx->abshash($table, \@columns, \%where, \@order); #returns {} |
767
|
|
|
|
|
|
|
my %hash = $dbx->abshash($table, \@columns, \%where, \@order); #returns () |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
=cut |
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
sub abshash { |
772
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
773
|
0
|
|
|
|
|
0
|
return $self->sqlhash($self->abs->select(@_)); |
774
|
|
|
|
|
|
|
} |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
=head2 abshashhash |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
Returns a hash where the keys are the values of the first column and the values are a hash reference of all (including the key) column values. |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
my $hash = $dbx->abshashhash($table, \@columns, \%where, \@order); #returns {} |
781
|
|
|
|
|
|
|
my %hash = $dbx->abshashhash($table, \@columns, \%where, \@order); #returns () |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
=cut |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
sub abshashhash { |
786
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
787
|
0
|
|
|
|
|
0
|
return $self->sqlhashhash($self->abs->select(@_)); |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
=head2 absarrayarray |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of array references ([],[],...) or [[],[],...] |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
my $array = $dbx->absarrayarray($table, \@columns, \%where, \@order); #returns [[$,$,...],[],[],...] |
796
|
|
|
|
|
|
|
my @array = $dbx->absarrayarray($table, \@columns, \%where, \@order); #returns ([$,$,...],[],[],...) |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
=cut |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
sub absarrayarray { |
801
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
802
|
0
|
|
|
|
|
0
|
return $self->sqlarrayarray($self->abs->select(@_)); |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
=head2 absarrayarrayname |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of array references ([],[],...) or [[],[],...] where the first row contains an array reference to the column names |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
my $array = $dbx->absarrayarrayname($table, \@columns, \%where, \@order); #returns [[$,$,...],[],[],...] |
810
|
|
|
|
|
|
|
my @array = $dbx->absarrayarrayname($table, \@columns, \%where, \@order); #returns ([$,$,...],[],[],...) |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=cut |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
sub absarrayarrayname { |
815
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
816
|
0
|
|
|
|
|
0
|
return $self->sqlarrayarrayname($self->abs->select(@_)); |
817
|
|
|
|
|
|
|
} |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
=head2 absarrayhash |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of hash references ({},{},...) or [{},{},...] |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
my $array = $dbx->absarrayhash($table, \@columns, \%where, \@order); #returns [{},{},{},...] |
824
|
|
|
|
|
|
|
my @array = $dbx->absarrayhash($table, \@columns, \%where, \@order); #returns ({},{},{},...) |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
=cut |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
sub absarrayhash { |
829
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
830
|
0
|
|
|
|
|
0
|
return $self->sqlarrayhash($self->abs->select(@_)); |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
=head2 absarrayhashname |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
Returns the SQL result as an array or array ref of hash references ({},{},...) or [{},{},...] where the first row contains an array reference to the column names. |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
my $array = $dbx->absarrayhashname($table, \@columns, \%where, \@order); #returns [[],{},{},...] |
838
|
|
|
|
|
|
|
my @array = $dbx->absarrayhashname($table, \@columns, \%where, \@order); #returns ([],{},{},...) |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
=cut |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
sub absarrayhashname { |
843
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
844
|
0
|
|
|
|
|
0
|
return $self->sqlarrayhashname($self->abs->select(@_)); |
845
|
|
|
|
|
|
|
} |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=head2 absarrayobject |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
Returns the SQL result as an array of blessed hash objects in to the $class namespace. |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
my $array = $dbx->absarrayobject($class, $table, \@columns, \%where, \@order); #returns [bless({}, $class), ...] |
852
|
|
|
|
|
|
|
my @array = $dbx->absarrayobject($class, $table, \@columns, \%where, \@order); #returns (bless({}, $class), ...) |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
=cut |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
sub absarrayobject { |
857
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
858
|
0
|
0
|
|
|
|
0
|
my $class = shift or die("Error: The absarrayobject method requires a class parameter"); |
859
|
0
|
|
|
|
|
0
|
my @objects = map {bless($_, $class)} $self->absarrayhash(@_); |
|
0
|
|
|
|
|
0
|
|
860
|
0
|
0
|
|
|
|
0
|
wantarray ? @objects : \@objects; |
861
|
|
|
|
|
|
|
} |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
=head1 METHODS (Read) - SQL + SQL::Abstract->where |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
=head2 sqlwhere |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
Returns SQL part appended with the WHERE and ORDER BY clauses |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
my ($sql, @bind) = $sql->sqlwhere($sqlpart, \%where, \@order); |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
Note: sqlwhere function should be ported into L RT125805 |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=cut |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
sub sqlwhere { |
876
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
877
|
0
|
|
|
|
|
0
|
my $sqlpart = shift; |
878
|
0
|
|
|
|
|
0
|
my ($where, @bind) = $self->abs->where(@_); |
879
|
0
|
0
|
|
|
|
0
|
$sqlpart .= " $/ $where" if length($where); |
880
|
0
|
|
|
|
|
0
|
return($sqlpart, @bind); |
881
|
|
|
|
|
|
|
} |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
=head2 sqlwherecursor |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
my $return = $sql->sqlwherecursor($sqlpart, \%where, \@order); |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
=cut |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
sub sqlwherecursor { |
890
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
891
|
0
|
|
|
|
|
0
|
return $self->sqlcursor($self->sqlwhere(@_)); |
892
|
|
|
|
|
|
|
} |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=head2 sqlwherescalar |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
my $return = $sql->sqlwherescalar($sqlpart, \%where, \@order); |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
=cut |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
sub sqlwherescalar { |
901
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
902
|
0
|
|
|
|
|
0
|
return $self->sqlscalar($self->sqlwhere(@_)); |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
=head2 sqlwherearray |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
my $return = $sql->sqlwherearray($sqlpart, \%where, \@order); |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
=cut |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
sub sqlwherearray { |
912
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
913
|
0
|
|
|
|
|
0
|
return $self->sqlarray($self->sqlwhere(@_)); |
914
|
|
|
|
|
|
|
} |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
=head2 sqlwherehash |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
my $return = $sql->sqlwherehash($sqlpart, \%where, \@order); |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
=cut |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
sub sqlwherehash { |
923
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
924
|
0
|
|
|
|
|
0
|
return $self->sqlhash($self->sqlwhere(@_)); |
925
|
|
|
|
|
|
|
} |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
=head2 sqlwherehashhash |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
my $return = $sql->sqlwherehashhash($sqlpart, \%where, \@order); |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
=cut |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
sub sqlwherehashhash { |
934
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
935
|
0
|
|
|
|
|
0
|
return $self->sqlhashhash($self->sqlwhere(@_)); |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
=head2 sqlwherearrayarray |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
my $return = $sql->sqlwherearrayarray($sqlpart, \%where, \@order); |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
=cut |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
sub sqlwherearrayarray { |
945
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
946
|
0
|
|
|
|
|
0
|
return $self->sqlarrayarray($self->sqlwhere(@_)); |
947
|
|
|
|
|
|
|
} |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
=head2 sqlwherearrayarrayname |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
my $return = $sql->sqlwherearrayarrayname($sqlpart, \%where, \@order); |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
=cut |
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
sub sqlwherearrayarrayname { |
956
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
957
|
0
|
|
|
|
|
0
|
return $self->sqlarrayarrayname($self->sqlwhere(@_)); |
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
=head2 sqlwherearrayhash |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
my $return = $sql->sqlwherearrayhash($sqlpart, \%where, \@order); |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
=cut |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
sub sqlwherearrayhash { |
967
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
968
|
0
|
|
|
|
|
0
|
return $self->sqlarrayhash($self->sqlwhere(@_)); |
969
|
|
|
|
|
|
|
} |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=head2 sqlwherearrayhashname |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
my $return = $sql->sqlwherearrayhashname($sqlpart, \%where, \@order); |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
=cut |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
sub sqlwherearrayhashname { |
978
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
979
|
0
|
|
|
|
|
0
|
return $self->sqlarrayhashname($self->sqlwhere(@_)); |
980
|
|
|
|
|
|
|
} |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
=head2 sqlwherearrayobject |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
my $return = $sql->sqlwherearrayobject($class, $sqlpart, \%where, \@order); |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
=cut |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
sub sqlwherearrayobject { |
989
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
990
|
0
|
0
|
|
|
|
0
|
my $class = shift or die("Error: sqlwherearrayobject parameter class missing"); |
991
|
0
|
|
|
|
|
0
|
return $self->sqlarrayobject($class, $self->sqlwhere(@_)); |
992
|
|
|
|
|
|
|
} |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
=head1 METHODS (Write) - SQL |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
Remember to commit or use AutoCommit |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
Note: It appears that some drivers do not support the count of rows. |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
=head2 sqlinsert, insert |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
Returns the number of rows inserted by the SQL statement. |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
my $count = $dbx->sqlinsert( $sql, @parameters); |
1005
|
|
|
|
|
|
|
my $count = $dbx->sqlinsert( $sql, \@parameters); |
1006
|
|
|
|
|
|
|
my $count = $dbx->sqlinsert( $sql, \%parameters); |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
=cut |
1009
|
|
|
|
|
|
|
|
1010
|
|
|
|
|
|
|
*sqlinsert = \&sqlupdate; |
1011
|
|
|
|
|
|
|
*insert = \&sqlupdate; |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
=head2 sqlupdate, update |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
Returns the number of rows updated by the SQL statement. |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
my $count = $dbx->sqlupdate( $sql, @parameters); |
1018
|
|
|
|
|
|
|
my $count = $dbx->sqlupdate( $sql, \@parameters); |
1019
|
|
|
|
|
|
|
my $count = $dbx->sqlupdate( $sql, \%parameters); |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
=cut |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
*update = \&sqlupdate; |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
sub sqlupdate { |
1026
|
19
|
|
|
19
|
1
|
10298
|
my $self = shift; |
1027
|
19
|
|
|
|
|
39
|
my $sql = shift; |
1028
|
19
|
50
|
|
|
|
68
|
my $sth = $self->sqlcursor($sql, @_) or die($self->errstr); |
1029
|
19
|
|
|
|
|
107
|
my $rows = $sth->rows; |
1030
|
19
|
|
|
|
|
129
|
$sth->finish; |
1031
|
19
|
|
|
|
|
263
|
return $rows; |
1032
|
|
|
|
|
|
|
} |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
=head2 sqldelete, delete |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
Returns the number of rows deleted by the SQL statement. |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
my $count = $dbx->sqldelete($sql, @parameters); |
1039
|
|
|
|
|
|
|
my $count = $dbx->sqldelete($sql, \@parameters); |
1040
|
|
|
|
|
|
|
my $count = $dbx->sqldelete($sql, \%parameters); |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
Note: Some Oracle clients do not support row counts on delete instead the value appears to be a success code. |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
=cut |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
*sqldelete = \&sqlupdate; |
1047
|
|
|
|
|
|
|
*delete = \&sqlupdate; |
1048
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
=head2 sqlexecute, execute, exec |
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
Executes stored procedures and generic SQL. |
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
my $out; |
1054
|
|
|
|
|
|
|
my $return = $dbx->sqlexecute($sql, $in, \$out); #pass in/out vars as scalar reference |
1055
|
|
|
|
|
|
|
my $return = $dbx->sqlexecute($sql, [$in, \$out]); |
1056
|
|
|
|
|
|
|
my $return = $dbx->sqlexecute($sql, {in=>$in, out=>\$out}); |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
Note: Currently sqlupdate, sqlinsert, sqldelete, and sqlexecute all point to the same method. This may change in the future if we need to change the behavior of one method. So, please use the correct method name for your function. |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
=cut |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
*sqlexecute = \&sqlupdate; |
1063
|
|
|
|
|
|
|
*execute = \&sqlupdate; #deprecated |
1064
|
|
|
|
|
|
|
*exec = \&sqlupdate; #deprecated |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
=head1 METHODS (Write) - SQL::Abstract |
1067
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
=head2 absinsert |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
Returns the number of rows inserted. |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
my $count = $dbx->absinsert($table, \%column_values); |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
=cut |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
sub absinsert { |
1077
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1078
|
0
|
|
|
|
|
|
return $self->sqlinsert($self->abs->insert(@_)); |
1079
|
|
|
|
|
|
|
} |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
=head2 absupdate |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
Returns the number of rows updated. |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
my $count = $dbx->absupdate($table, \%column_values, \%where); |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
=cut |
1088
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
sub absupdate { |
1090
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1091
|
0
|
|
|
|
|
|
return $self->sqlupdate($self->abs->update(@_)); |
1092
|
|
|
|
|
|
|
} |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
=head2 absdelete |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
Returns the number of rows deleted. |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
my $count = $dbx->absdelete($table, \%where); |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
=cut |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
sub absdelete { |
1103
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1104
|
0
|
|
|
|
|
|
return $self->sqldelete($self->abs->delete(@_)); |
1105
|
|
|
|
|
|
|
} |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
=head1 METHODS (Write) - Bulk - SQL |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
=head2 bulksqlinsertarrayarray |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
Insert records in bulk. |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
my @arrayarray = ( |
1114
|
|
|
|
|
|
|
[$data1, $data2, $data3, $data4, ...], |
1115
|
|
|
|
|
|
|
[@row_data_2], |
1116
|
|
|
|
|
|
|
[@row_data_3], ... |
1117
|
|
|
|
|
|
|
); |
1118
|
|
|
|
|
|
|
my $count = $dbx->bulksqlinsertarrayarray($sql, \@arrayarray); |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
=cut |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
sub bulksqlinsertarrayarray { |
1123
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1124
|
0
|
0
|
|
|
|
|
my $sql = shift or die('Error: sql required.'); |
1125
|
0
|
0
|
|
|
|
|
my $arrayarray = shift or die('Error: array of array references required.'); |
1126
|
0
|
|
|
|
|
|
my $sth = $self->prepare($sql); |
1127
|
0
|
|
|
|
|
|
my $rows = 0; |
1128
|
0
|
|
|
|
|
|
my $size = @$arrayarray; |
1129
|
0
|
|
|
|
|
|
my @tuple_status = (); |
1130
|
0
|
|
|
0
|
|
|
my ($tupples, $count) = $sth->execute_for_fetch( sub {shift @$arrayarray}, \@tuple_status); |
|
0
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
#print Dumper \@tuple_status, $tupples, $count; |
1132
|
0
|
0
|
|
|
|
|
if (not defined $count) { #driver does not support count yet |
1133
|
0
|
|
|
|
|
|
foreach my $status (@tuple_status) { |
1134
|
0
|
0
|
|
|
|
|
if (ref($status) eq "ARRAR") { |
|
|
0
|
|
|
|
|
|
1135
|
0
|
|
|
|
|
|
warn($status->[1]); |
1136
|
|
|
|
|
|
|
} elsif ($status == -1) { |
1137
|
0
|
|
|
|
|
|
$rows++; #no error assume 1 row inserted. |
1138
|
|
|
|
|
|
|
} else { |
1139
|
0
|
|
|
|
|
|
warn(Dumper $status); |
1140
|
|
|
|
|
|
|
} |
1141
|
|
|
|
|
|
|
} |
1142
|
0
|
|
|
|
|
|
$count = $rows; |
1143
|
|
|
|
|
|
|
} |
1144
|
0
|
|
|
|
|
|
return $count; |
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
=head2 bulksqlinsertarrayhash |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
Insert records in bulk. |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
my @columns = ("Col1", "Col2", "Col3", "Col4", ...); #case sensitive with respect to @arrayhash |
1152
|
|
|
|
|
|
|
my @arrayhash = ( |
1153
|
|
|
|
|
|
|
{C0l1=>data1, Col2=>$data2, Col3=>$data3, Col4=>$data4, ...}, #extra hash items ignored when sliced using @columns |
1154
|
|
|
|
|
|
|
\%row_hash_data_2, |
1155
|
|
|
|
|
|
|
\%row_hash_data_3, ... |
1156
|
|
|
|
|
|
|
); |
1157
|
|
|
|
|
|
|
my $count = $dbx->bulksqlinsertarrayhash($sql, \@columns, \@arrayhash); |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
=cut |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
sub bulksqlinsertarrayhash { |
1162
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1163
|
0
|
0
|
|
|
|
|
my $sql = shift or die("Error: SQL required."); |
1164
|
0
|
0
|
|
|
|
|
my $columns = shift or die("Error: columns array reference required."); |
1165
|
0
|
0
|
|
|
|
|
my $arrayhash = shift or die("Error: array of hash references required."); |
1166
|
0
|
|
|
|
|
|
my @arrayarray = map {my %hash = %$_; my @slice = @hash{@$columns}; \@slice} @$arrayhash; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1167
|
0
|
|
|
|
|
|
return $self->bulksqlinsertarrayarray($sql, \@arrayarray); |
1168
|
|
|
|
|
|
|
} |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
=head2 bulksqlinsertcursor |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
Insert records in bulk. |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
Step 1 select data from table 1 in database 1 |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
my $sth1 = $dbx1->sqlcursor('Select Col1 AS "ColA", Col2 AS "ColB", Col3 AS "ColC" from table1'); |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
Step 2 insert in to table 2 in database 2 |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
my $count = $dbx2->bulksqlinsertcursor($sql, $sth1); |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
Note: If you are inside a single database, it is much more efficient to use insert from select syntax as no data needs to be transferred to and from the client. |
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
=cut |
1185
|
|
|
|
|
|
|
|
1186
|
|
|
|
|
|
|
sub bulksqlinsertcursor { |
1187
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1188
|
0
|
0
|
|
|
|
|
my $sql = shift or die('Error: sql required.'); |
1189
|
0
|
0
|
|
|
|
|
my $cursor = shift or die('Error: cursor required.'); |
1190
|
0
|
|
|
|
|
|
my $sth = $self->prepare($sql); |
1191
|
0
|
|
|
|
|
|
my @tuple_status = (); |
1192
|
0
|
|
|
|
|
|
my $size = 0; |
1193
|
0
|
0
|
|
0
|
|
|
my $count = $sth->execute_for_fetch( sub {my $row = $cursor->fetchrow_arrayref; $size++ if $row; return $row}, \@tuple_status); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1194
|
0
|
0
|
|
|
|
|
unless ($count == $size) { |
1195
|
0
|
|
|
|
|
|
warn Dumper \@tuple_status; #TODO better error trapping... |
1196
|
|
|
|
|
|
|
} |
1197
|
0
|
|
|
|
|
|
return $count; |
1198
|
|
|
|
|
|
|
} |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
=head2 bulksqlupdatearrayarray |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
Update records in bulk. |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
my @arrayarray = ( |
1205
|
|
|
|
|
|
|
[$data1, $data2, $data3, $data4, $id], |
1206
|
|
|
|
|
|
|
[@row_data_2], |
1207
|
|
|
|
|
|
|
[@row_data_3], ... |
1208
|
|
|
|
|
|
|
); |
1209
|
|
|
|
|
|
|
my $count = $dbx->bulksqlupdatearrayarray($sql, \@arrayarray); |
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
=cut |
1212
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
sub bulksqlupdatearrayarray { |
1214
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1215
|
0
|
0
|
|
|
|
|
my $sql = shift or die('Error: sql required.'); |
1216
|
0
|
0
|
|
|
|
|
my $arrayarray = shift or die('Error: array of array references required.'); |
1217
|
0
|
|
|
|
|
|
my $sth = $self->prepare($sql); |
1218
|
0
|
|
|
|
|
|
my $size = @$arrayarray; |
1219
|
0
|
|
|
|
|
|
my @tuple_status = (); #pass to set $tupples |
1220
|
0
|
|
|
0
|
|
|
my ($tupples, $count) = $sth->execute_for_fetch( sub {shift @$arrayarray}, \@tuple_status); |
|
0
|
|
|
|
|
|
|
1221
|
0
|
0
|
|
|
|
|
warn("Warning: Attempted $size transactions but only $tupples where successful.") unless $size == $tupples; |
1222
|
|
|
|
|
|
|
#warn Dumper \@tuple_status; |
1223
|
0
|
0
|
0
|
|
|
|
unless (defined($count) and $count >= 0) { |
1224
|
0
|
|
|
|
|
|
$count = sum(0, grep {$_ > 0} grep {not ref($_)} @tuple_status); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
} |
1226
|
0
|
|
|
|
|
|
return $count; |
1227
|
|
|
|
|
|
|
} |
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
=head1 METHODS (Write) - Bulk - SQL::Abstract-like |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
These bulk methods do not use L but our own similar SQL insert and update methods. |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
=head2 bulkabsinsertarrayarray |
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
Insert records in bulk. |
1236
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
my @columns = ("Col1", "Col2", "Col3", "Col4", ...); |
1238
|
|
|
|
|
|
|
my @arrayarray = ( |
1239
|
|
|
|
|
|
|
[data1, $data2, $data3, $data4, ...], |
1240
|
|
|
|
|
|
|
[@row_data_2], |
1241
|
|
|
|
|
|
|
[@row_data_3], ... |
1242
|
|
|
|
|
|
|
); |
1243
|
|
|
|
|
|
|
my $count = $dbx->bulkabsinsertarrayarray($table, \@columns, \@arrayarray); |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
=cut |
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
sub bulkabsinsertarrayarray { |
1248
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1249
|
0
|
0
|
|
|
|
|
my $table = shift or die('Error: table name required.'); |
1250
|
0
|
0
|
|
|
|
|
my $columns = shift or die('Error: columns array reference required.'); |
1251
|
0
|
0
|
|
|
|
|
my $arrayarray = shift or die('Error: array of array references required.'); |
1252
|
0
|
|
|
|
|
|
my $sql = $self->_bulkinsert_sql($table => $columns); |
1253
|
0
|
|
|
|
|
|
return $self->bulksqlinsertarrayarray($sql, $arrayarray); |
1254
|
|
|
|
|
|
|
} |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
=head2 bulkabsinsertarrayhash |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
Insert records in bulk. |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
my @columns = ("Col1", "Col2", "Col3", "Col4", ...); #case sensitive with respect to @arrayhash |
1261
|
|
|
|
|
|
|
my @arrayhash = ( |
1262
|
|
|
|
|
|
|
{C0l1=>data1, Col2=>$data2, Col3=>$data3, Col4=>$data4, ...}, #extra hash items ignored when sliced using @columns |
1263
|
|
|
|
|
|
|
\%row_hash_data_2, |
1264
|
|
|
|
|
|
|
\%row_hash_data_3, ... |
1265
|
|
|
|
|
|
|
); |
1266
|
|
|
|
|
|
|
my $count = $dbx->bulkabsinsertarrayhash($table, \@columns, \@arrayhash); |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
=cut |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
sub bulkabsinsertarrayhash { |
1271
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1272
|
0
|
0
|
|
|
|
|
my $table = shift or die("Error: table name required."); |
1273
|
0
|
0
|
|
|
|
|
my $columns = shift or die("Error: columns array reference required."); |
1274
|
0
|
0
|
|
|
|
|
my $arrayhash = shift or die("Error array of hash references required"); |
1275
|
0
|
|
|
|
|
|
my @arrayarray = map {my %hash = %$_; my @slice = @hash{@$columns}; \@slice} @$arrayhash; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1276
|
0
|
|
|
|
|
|
return $self->bulkabsinsertarrayarray($table, $columns, \@arrayarray); |
1277
|
|
|
|
|
|
|
} |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
=head2 bulkabsinsertcursor |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
Insert records in bulk. |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
Step 1 select data from table 1 in database 1 |
1284
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
my $sth1 = $dbx1->sqlcursor('Select Col1 AS "ColA", Col2 AS "ColB", Col3 AS "ColC" from table1'); |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
Step 2 insert in to table 2 in database 2 |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
my $count = $dbx2->bulkabsinsertcursor($table2, $sth1); |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
my $count = $dbx2->bulkabsinsertcursor($table2, \@columns, $sth1); #if your DBD/API does not support column alias support |
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
Note: If you are inside a single database, it is much more efficient to use insert from select syntax as no data needs to be transferred to and from the client. |
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
=cut |
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
sub bulkabsinsertcursor { |
1298
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1299
|
0
|
0
|
|
|
|
|
my $table = shift or die('Error: table name required.'); |
1300
|
0
|
0
|
|
|
|
|
my $cursor = pop or die('Error: cursor required.'); |
1301
|
0
|
|
0
|
|
|
|
my $columns = shift || $cursor->{'NAME'}; |
1302
|
0
|
|
|
|
|
|
my $sql = $self->_bulkinsert_sql($table => $columns); |
1303
|
0
|
|
|
|
|
|
return $self->bulksqlinsertcursor($sql, $cursor); |
1304
|
|
|
|
|
|
|
} |
1305
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
#head2 _bulkinsert_sql |
1307
|
|
|
|
|
|
|
# |
1308
|
|
|
|
|
|
|
#Our own method since SQL::Abstract does not support ordered column values |
1309
|
|
|
|
|
|
|
# |
1310
|
|
|
|
|
|
|
#cut |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
sub _bulkinsert_sql { |
1313
|
0
|
|
|
0
|
|
|
my $self = shift; |
1314
|
0
|
|
|
|
|
|
my $table = shift; |
1315
|
0
|
|
|
|
|
|
my $columns = shift; |
1316
|
0
|
|
|
|
|
|
my $sql = sprintf("INSERT INTO $table (%s) VALUES (%s)", join(',', @$columns), join(',', map {'?'} @$columns)); |
|
0
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
#warn "$sql\n"; |
1318
|
0
|
|
|
|
|
|
return $sql; |
1319
|
|
|
|
|
|
|
} |
1320
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
=head2 bulkabsupdatearrayarray |
1322
|
|
|
|
|
|
|
|
1323
|
|
|
|
|
|
|
Update records in bulk. |
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
my @setcolumns = ("Col1", "Col2", "Col3", "Col4"); |
1326
|
|
|
|
|
|
|
my @wherecolumns = ("ID"); |
1327
|
|
|
|
|
|
|
my @arrayarray = ( |
1328
|
|
|
|
|
|
|
[$data1, $data2, $data3, $data4, $id], |
1329
|
|
|
|
|
|
|
[@row_data_2], |
1330
|
|
|
|
|
|
|
[@row_data_3], ... |
1331
|
|
|
|
|
|
|
); |
1332
|
|
|
|
|
|
|
my $count = $dbx->bulkabsupdatearrayarray($table, \@setcolumns, \@wherecolumns, \@arrayarray); |
1333
|
|
|
|
|
|
|
|
1334
|
|
|
|
|
|
|
=cut |
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
sub bulkabsupdatearrayarray { |
1337
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1338
|
0
|
0
|
|
|
|
|
my $table = shift or die('Error: table name required.'); |
1339
|
0
|
0
|
|
|
|
|
my $setcolumns = shift or die('Error: set columns array reference required.'); |
1340
|
0
|
0
|
|
|
|
|
my $wherecolumns = shift or die('Error: where columns array reference required.'); |
1341
|
0
|
|
|
|
|
|
my $arrayarray = shift; |
1342
|
0
|
|
|
|
|
|
my $sql = $self->_bulkupdate_sql($table => $setcolumns, $wherecolumns); |
1343
|
0
|
|
|
|
|
|
return $self->bulksqlupdatearrayarray($sql, $arrayarray); |
1344
|
|
|
|
|
|
|
} |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
#head2 _bulkupdate_sql |
1347
|
|
|
|
|
|
|
# |
1348
|
|
|
|
|
|
|
#Our own method since SQL::Abstract does not support ordered column values |
1349
|
|
|
|
|
|
|
# |
1350
|
|
|
|
|
|
|
##cut |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
sub _bulkupdate_sql { |
1353
|
0
|
|
|
0
|
|
|
my $self = shift; |
1354
|
0
|
|
|
|
|
|
my $table = shift; |
1355
|
0
|
|
|
|
|
|
my $setcolumns = shift; |
1356
|
0
|
|
|
|
|
|
my $wherecolumns = shift; |
1357
|
0
|
|
|
|
|
|
my $sql = sprintf("UPDATE $table SET %s WHERE %s", join(", ", map {"$_ = ?"} @$setcolumns), join(" AND ", map {"$_ = ?"} @$wherecolumns)); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
#warn "$sql\n"; |
1359
|
0
|
|
|
|
|
|
return $sql; |
1360
|
|
|
|
|
|
|
} |
1361
|
|
|
|
|
|
|
|
1362
|
|
|
|
|
|
|
=head1 Constructors |
1363
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
=head2 abs |
1365
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
Returns a L object |
1367
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
=cut |
1369
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
sub abs { |
1371
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1372
|
0
|
0
|
|
|
|
|
$self->{'abs'} = shift if @_; |
1373
|
0
|
0
|
|
|
|
|
unless (defined $self->{'abs'}) { |
1374
|
0
|
|
|
|
|
|
eval 'use SQL::Abstract'; #run time require so as not to require installation for all users |
1375
|
0
|
|
|
|
|
|
my $error = $@; |
1376
|
0
|
0
|
|
|
|
|
die($error) if $error; |
1377
|
0
|
|
|
|
|
|
$self->{'abs'} = SQL::Abstract->new; |
1378
|
|
|
|
|
|
|
} |
1379
|
0
|
|
|
|
|
|
return $self->{'abs'}; |
1380
|
|
|
|
|
|
|
} |
1381
|
|
|
|
|
|
|
|
1382
|
|
|
|
|
|
|
=head1 Methods (Informational) |
1383
|
|
|
|
|
|
|
|
1384
|
|
|
|
|
|
|
=head2 dbms_name |
1385
|
|
|
|
|
|
|
|
1386
|
|
|
|
|
|
|
Return the DBMS Name (e.g. Oracle, MySQL, PostgreSQL) |
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
=cut |
1389
|
|
|
|
|
|
|
|
1390
|
0
|
|
|
0
|
1
|
|
sub dbms_name {shift->dbh->get_info(17)}; |
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
=head1 Methods (Session Management) |
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
These methods allow the setting of Oracle session features that are available in the v$session table. If other databases support these features, please let me know. But, as it stands, these methods are non operational unless SQL_DBMS_NAME is Oracle. |
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
=head2 module |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
Sets and returns the v$session.module (Oracle) value. |
1399
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
Note: Module is set for you by DBD::Oracle. However you may set it however you'd like. It should be set once after connection and left alone. |
1401
|
|
|
|
|
|
|
|
1402
|
|
|
|
|
|
|
$dbx->module("perl@host"); #normally set by DBD::Oracle |
1403
|
|
|
|
|
|
|
$dbx->module($module, $action); #can set initial action too. |
1404
|
|
|
|
|
|
|
my $module = $dbx->module(); |
1405
|
|
|
|
|
|
|
|
1406
|
|
|
|
|
|
|
=cut |
1407
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
sub module { |
1409
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1410
|
0
|
0
|
|
|
|
|
return unless $self->dbms_name eq 'Oracle'; |
1411
|
0
|
0
|
|
|
|
|
if (@_) { |
1412
|
0
|
|
|
|
|
|
my $module = shift; |
1413
|
0
|
|
|
|
|
|
my $action = shift; |
1414
|
0
|
|
|
|
|
|
$self->sqlexecute($self->_set_module_sql, $module, $action); |
1415
|
|
|
|
|
|
|
} |
1416
|
0
|
0
|
|
|
|
|
if (defined wantarray) { |
1417
|
0
|
|
|
|
|
|
return $self->sqlscalar($self->_sys_context_userenv_sql, 'MODULE'); |
1418
|
|
|
|
|
|
|
} else { |
1419
|
0
|
|
|
|
|
|
return; #void context no need to hit the database |
1420
|
|
|
|
|
|
|
} |
1421
|
|
|
|
|
|
|
} |
1422
|
|
|
|
|
|
|
|
1423
|
|
|
|
|
|
|
sub _set_module_sql { |
1424
|
0
|
|
|
0
|
|
|
return qq{/* be655786-bcbe-11e5-8338-005056a31307 */ |
1425
|
|
|
|
|
|
|
/* Script: $0 */ |
1426
|
|
|
|
|
|
|
/* Package: $PACKAGE */ |
1427
|
|
|
|
|
|
|
/* Method: _set_module_sql */ |
1428
|
|
|
|
|
|
|
BEGIN |
1429
|
|
|
|
|
|
|
DBMS_APPLICATION_INFO.set_module(module_name => ?, action_name => ?); |
1430
|
|
|
|
|
|
|
END; |
1431
|
|
|
|
|
|
|
}; |
1432
|
|
|
|
|
|
|
} |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
=head2 client_info |
1435
|
|
|
|
|
|
|
|
1436
|
|
|
|
|
|
|
Sets and returns the v$session.client_info (Oracle) value. |
1437
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
$dbx->client_info("Running From crontab"); |
1439
|
|
|
|
|
|
|
my $client_info = $dbx->client_info(); |
1440
|
|
|
|
|
|
|
|
1441
|
|
|
|
|
|
|
You may use this field for anything up to 64 characters! |
1442
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
$dbx->client_info(join "~", (ver => 4, realm => "ldap", grp =>25)); #tilde is a fairly good separator |
1444
|
|
|
|
|
|
|
my %client_info = split(/~/, $dbx->client_info()); |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
=cut |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
sub client_info { |
1449
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1450
|
0
|
0
|
|
|
|
|
return unless $self->dbms_name eq 'Oracle'; |
1451
|
0
|
0
|
|
|
|
|
if (@_) { |
1452
|
0
|
|
|
|
|
|
my $text = shift; |
1453
|
0
|
|
|
|
|
|
$self->sqlexecute($self->_set_client_info_sql, $text); |
1454
|
|
|
|
|
|
|
} |
1455
|
0
|
0
|
|
|
|
|
if (defined wantarray) { |
1456
|
0
|
|
|
|
|
|
return $self->sqlscalar($self->_sys_context_userenv_sql, 'CLIENT_INFO'); |
1457
|
|
|
|
|
|
|
} else { |
1458
|
0
|
|
|
|
|
|
return; #void context no need to hit the database |
1459
|
|
|
|
|
|
|
} |
1460
|
|
|
|
|
|
|
} |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
sub _set_client_info_sql { |
1463
|
0
|
|
|
0
|
|
|
return qq{/* d04d0138-bcbe-11e5-b0e3-005056a31307 */ |
1464
|
|
|
|
|
|
|
/* Script: $0 */ |
1465
|
|
|
|
|
|
|
/* Package: $PACKAGE */ |
1466
|
|
|
|
|
|
|
/* Method: _set_client_info_sql */ |
1467
|
|
|
|
|
|
|
BEGIN |
1468
|
|
|
|
|
|
|
DBMS_APPLICATION_INFO.set_client_info(client_info => ?); |
1469
|
|
|
|
|
|
|
END; |
1470
|
|
|
|
|
|
|
}; |
1471
|
|
|
|
|
|
|
} |
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
=head2 action |
1474
|
|
|
|
|
|
|
|
1475
|
|
|
|
|
|
|
Sets and returns the v$session.action (Oracle) value. |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
$dbx->action("We are Here"); |
1478
|
|
|
|
|
|
|
my $action = $dbx->action(); |
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
Note: This should be updated fairly often. Every loop if it runs for more than 5 seconds and may end up in V$SQL_MONITOR. |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
while ($this) { |
1483
|
|
|
|
|
|
|
local $dbx->{'action'} = "This Loop"; #tied to the database with a little Perl sugar |
1484
|
|
|
|
|
|
|
} |
1485
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
=cut |
1487
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
sub action { |
1489
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1490
|
0
|
0
|
|
|
|
|
return unless $self->dbms_name eq 'Oracle'; |
1491
|
0
|
0
|
|
|
|
|
if (@_) { |
1492
|
0
|
|
|
|
|
|
my $text = shift; |
1493
|
0
|
|
|
|
|
|
$self->sqlexecute($self->_set_action_sql, $text); |
1494
|
|
|
|
|
|
|
} |
1495
|
0
|
0
|
|
|
|
|
if (defined wantarray) { |
1496
|
0
|
|
|
|
|
|
return $self->sqlscalar($self->_sys_context_userenv_sql, 'ACTION'); |
1497
|
|
|
|
|
|
|
} else { |
1498
|
0
|
|
|
|
|
|
return; #void context no need to hit the database |
1499
|
|
|
|
|
|
|
} |
1500
|
|
|
|
|
|
|
} |
1501
|
|
|
|
|
|
|
|
1502
|
|
|
|
|
|
|
sub _set_action_sql { |
1503
|
0
|
|
|
0
|
|
|
return qq{/* e682f1a6-bcbe-11e5-bd3e-005056a31307 */ |
1504
|
|
|
|
|
|
|
/* Script: $0 */ |
1505
|
|
|
|
|
|
|
/* Package: $PACKAGE */ |
1506
|
|
|
|
|
|
|
/* Method: _set_action_sql */ |
1507
|
|
|
|
|
|
|
BEGIN |
1508
|
|
|
|
|
|
|
DBMS_APPLICATION_INFO.set_action(action_name => ?); |
1509
|
|
|
|
|
|
|
END; |
1510
|
|
|
|
|
|
|
}; |
1511
|
|
|
|
|
|
|
} |
1512
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
=head2 client_identifier |
1514
|
|
|
|
|
|
|
|
1515
|
|
|
|
|
|
|
Sets and returns the v$session.client_identifier (Oracle) value. |
1516
|
|
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
$dbx->client_identifier($login); |
1518
|
|
|
|
|
|
|
my $client_identifier = $dbx->client_identifier(); |
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
Note: This should be updated based on the login of the authenticated end user. I use the client_info->{'realm'} if you have more than one authentication realm. |
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
For auditing add this to an update trigger |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
new.UPDATED_USER = sys_context('USERENV', 'CLIENT_IDENTIFIER'); |
1525
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
=cut |
1527
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
sub client_identifier { |
1529
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
1530
|
0
|
0
|
|
|
|
|
return unless $self->dbms_name eq 'Oracle'; |
1531
|
0
|
0
|
|
|
|
|
if (@_) { |
1532
|
0
|
|
|
|
|
|
my $text = shift; |
1533
|
0
|
|
|
|
|
|
$self->sqlexecute($self->_set_client_identifier_sql, $text); |
1534
|
|
|
|
|
|
|
} |
1535
|
0
|
0
|
|
|
|
|
if (defined wantarray) { |
1536
|
0
|
|
|
|
|
|
return $self->sqlscalar($self->_sys_context_userenv_sql, 'CLIENT_IDENTIFIER'); |
1537
|
|
|
|
|
|
|
} else { |
1538
|
0
|
|
|
|
|
|
return; #void context no need to hit the database |
1539
|
|
|
|
|
|
|
} |
1540
|
|
|
|
|
|
|
} |
1541
|
|
|
|
|
|
|
|
1542
|
|
|
|
|
|
|
sub _set_client_identifier_sql { |
1543
|
0
|
|
|
0
|
|
|
return qq{/* f8226e6e-bcbe-11e5-91b8-005056a31307 */ |
1544
|
|
|
|
|
|
|
/* Script: $0 */ |
1545
|
|
|
|
|
|
|
/* Package: $PACKAGE */ |
1546
|
|
|
|
|
|
|
/* Method: _set_client_identifier_sql */ |
1547
|
|
|
|
|
|
|
BEGIN |
1548
|
|
|
|
|
|
|
DBMS_SESSION.SET_IDENTIFIER(client_id => ?); |
1549
|
|
|
|
|
|
|
END; |
1550
|
|
|
|
|
|
|
}; |
1551
|
|
|
|
|
|
|
} |
1552
|
|
|
|
|
|
|
|
1553
|
|
|
|
|
|
|
sub _sys_context_userenv_sql { |
1554
|
0
|
|
|
0
|
|
|
return qq{/* 09648e1e-bcbf-11e5-916a-005056a31307 */ |
1555
|
|
|
|
|
|
|
/* Script: $0 */ |
1556
|
|
|
|
|
|
|
/* Package: $PACKAGE */ |
1557
|
|
|
|
|
|
|
/* Method: _sys_context_userenv_sql */ |
1558
|
|
|
|
|
|
|
SELECT sys_context('USERENV',?) |
1559
|
|
|
|
|
|
|
FROM SYS.DUAL |
1560
|
|
|
|
|
|
|
}; |
1561
|
|
|
|
|
|
|
} |
1562
|
|
|
|
|
|
|
|
1563
|
|
|
|
|
|
|
=head1 TODO |
1564
|
|
|
|
|
|
|
|
1565
|
|
|
|
|
|
|
Sort functions sqlsort and sqlarrayarraynamesort may not be portable. It is now recommend to use sqlwhere methods instead. |
1566
|
|
|
|
|
|
|
|
1567
|
|
|
|
|
|
|
Add some kind of capability to allow hash binds to bind as some native type rather than all strings. |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
Hash binds scan comments for bind variables e.g. /* :variable */ |
1570
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
Improve error messages |
1572
|
|
|
|
|
|
|
|
1573
|
|
|
|
|
|
|
=head1 BUGS |
1574
|
|
|
|
|
|
|
|
1575
|
|
|
|
|
|
|
Please open on GitHub |
1576
|
|
|
|
|
|
|
|
1577
|
|
|
|
|
|
|
=head1 AUTHOR |
1578
|
|
|
|
|
|
|
|
1579
|
|
|
|
|
|
|
Michael R. Davis |
1580
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1582
|
|
|
|
|
|
|
|
1583
|
|
|
|
|
|
|
MIT License |
1584
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
Copyright (c) 2023 Michael R. Davis |
1586
|
|
|
|
|
|
|
|
1587
|
|
|
|
|
|
|
=head1 SEE ALSO |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
=head2 The Competition |
1590
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
L, L, L, L, L, L, L quick_*, L (arrays & hashes) |
1592
|
|
|
|
|
|
|
|
1593
|
|
|
|
|
|
|
=head2 The Building Blocks |
1594
|
|
|
|
|
|
|
|
1595
|
|
|
|
|
|
|
L, L |
1596
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
=cut |
1598
|
|
|
|
|
|
|
|
1599
|
|
|
|
|
|
|
1; |