line
stmt
bran
cond
sub
pod
time
code
1
#
2
# $Id: Table.pm,v 1.25 2007-01-27 13:35:02 gomor Exp $
3
#
4
5
package DBIx::SQLite::Simple::Table;
6
3
3
1384
use strict;
3
5
3
99
7
3
3
12
use warnings;
3
4
3
69
8
3
3
10
use Carp;
3
3
3
4835
9
10
require Class::Gomor::Array;
11
our @ISA = qw(Class::Gomor::Array);
12
13
our @AS = qw(
14
dbo
15
);
16
__PACKAGE__->cgBuildIndices;
17
__PACKAGE__->cgBuildAccessorsScalar(\@AS);
18
19
require DBIx::SQLite::Simple;
20
21
# XXX: do all SQL request with prepare/execute
22
23
=head1 NAME
24
25
DBIx::SQLite::Simple::Table - superclass only used to handle SQL tables
26
27
=head1 SYNOPSIS
28
29
# Example of a table with a primary key
30
31
package TPub;
32
33
require DBIx::SQLite::Simple::Table;
34
our @ISA = qw(DBIx::SQLite::Simple::Table);
35
36
our @AS = qw(
37
idPub
38
pub
39
);
40
__PACKAGE__->cgBuildIndices;
41
__PACKAGE__->cgBuildAccessorsScalar(\@AS);
42
43
# 'our $Id' and 'our @Fields' are named Id and Fields for a good
44
# reason, so do not name these variables by another name.
45
our $Id = $AS[0];
46
our @Fields = @AS[1..$#AS];
47
48
1;
49
50
# Example of a table with no key at all
51
52
package TBeer;
53
54
require DBIx::SQLite::Simple::Table;
55
our @ISA = qw(DBIx::SQLite::Simple::Table);
56
57
our @AS = qw(
58
beer
59
country
60
);
61
__PACKAGE__->cgBuildIndices;
62
__PACKAGE__->cgBuildAccessorsScalar(\@AS);
63
64
our @Fields = @AS;
65
66
1;
67
68
# Now, we have two tables, we can play with the database
69
70
package main;
71
72
require DBIx::SQLite::Simple;
73
my $db = DBIx::SQLite::Simple->new(db => 'sqlite.db');
74
75
# Create to object to play with the two tables
76
my $tPub = TPub->new;
77
my $tBeer = TBeer->new;
78
79
# Create tables
80
$tPub->create unless $tPub->exists;
81
$tBeer->create unless $tBeer->exists;
82
83
# Create some entries
84
my @pubEntries;
85
push @pubEntries, TPub->new(pub => $_) for (qw(corner friends));
86
87
my @beerEntries;
88
push @beerEntries, TBeer->new(beer => $_, country => 'BE')
89
for (qw(grim leffe bud));
90
91
# Now insert those entries;
92
$tPub->insert(\@pubEntries);
93
$tBeer->insert(\@beerEntries);
94
95
# Get friends pub
96
my $friends = $tPub->select(pub => 'friends');
97
98
# Lookup id
99
my $id = $tPub->lookupId(pub => 'friends');
100
101
# Lookup string
102
my $str = $tPub->lookupString('pub', idPub => $id);
103
104
# Add a beer from 'chez moi'
105
my $dremmwel = TBeer->new(beer => 'Dremmwel', country => '?');
106
$tBeer->insert([ $dremmwel ]);
107
108
$tPub->commit;
109
$tBeer->commit;
110
111
# Update Dremmwel
112
my $dremmwelOld = $dremmwel->cgClone;
113
$dremmwel->country('BZH');
114
$tBeer->update([ $dremmwel ], $dremmwelOld);
115
$tBeer->commit;
116
117
# Delete all pubs
118
$tPub->delete(\@pubEntries);
119
120
=head1 ATTRIBUTES
121
122
=over 4
123
124
=item B
125
126
Stores a DBIx::SQLite::Simple object.
127
128
=back
129
130
=head1 METHODS
131
132
=over 4
133
134
=item B
135
136
Object creator. Will return an object used to access corresponding SQL table. You can pass an optional parameter: dbo. By default, it uses the global variable $DBIx::SQLite::Simple::Dbo.
137
138
=cut
139
140
sub new {
141
16
16
1
88
my $self = shift->SUPER::new(@_);
142
143
16
50
2052
$self->dbo($DBIx::SQLite::Simple::Dbo)
144
unless $self->dbo;
145
146
16
239
$self;
147
}
148
149
sub __toObj {
150
4
4
7
my $self = shift;
151
4
8
my ($fields, $aref) = @_;
152
153
4
5
my $class = ref($self);
154
155
4
6
my @obj = ();
156
4
9
for my $h (@$aref) {
157
9
13
my %values = map { $_ => $h->{$_} } @$fields;
18
47
158
9
25
push @obj, $class->new(%values);
159
}
160
4
64
\@obj;
161
}
162
163
0
0
0
sub _carp { shift; carp("@{[(caller(0))[3]]}: ".shift()."\n"); undef }
0
0
0
0
0
0
164
165
sub _create {
166
2
2
3
my $self = shift;
167
2
4
my ($fields, $noKey) = @_;
168
169
2
12
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
170
171
2
11
my $query = 'CREATE TABLE '. $table. '(';
172
2
100
7
if ($noKey) {
173
1
2
$query .= $fields->[0]. ', ';
174
}
175
else {
176
1
4
$query .= $fields->[0]. ' INTEGER PRIMARY KEY, ';
177
}
178
2
3
shift(@$fields);
179
2
7
$query .= $_. ', ' for @$fields;
180
2
8
$query =~ s/, $/)/;
181
182
2
7
$self->dbo->_dbh->do($query);
183
184
2
50
818
return $self->_carp('_create: do: query['.$query.']: '.
185
$self->dbo->_dbh->errstr)
186
if $self->dbo->_dbh->err;
187
188
2
39
1;
189
}
190
191
=item B
192
193
Just a convenient method to commit pending changes to the whole database.
194
195
=cut
196
197
8
8
1
52
sub commit { shift->dbo->commit }
198
199
sub _exists {
200
2
2
3
my $self = shift;
201
202
2
13
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
203
204
2
5
$self->dbo->_dbh->do('SELECT * FROM '. $table);
205
2
50
534
$self->dbo->_dbh->err ? undef : 1;
206
}
207
208
sub _delete {
209
2
2
4
my $self = shift;
210
2
4
my ($fields, $values) = @_;
211
212
2
21
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
213
214
2
9
my $query = 'DELETE FROM '. $table. ' WHERE ';
215
2
13
$query .= $_. '=? AND ' for @$fields;
216
2
13
$query =~ s/ AND $//;
217
2
16
my $sth = $self->dbo->_dbh->prepare($query);
218
219
2
50
362
return $self->_carp('_delete: prepare: query['.$query.']: '.
220
$self->dbo->_dbh->errstr)
221
if $self->dbo->_dbh->err;
222
223
2
48
for my $obj (@$values) {
224
5
71
my @fields;
225
5
22
push @fields, $obj->$_ for @$fields;
226
5
618
$sth->execute(@fields);
227
228
5
50
34
return $self->_carp('_delete: execute: '.$self->dbo->_dbh->errstr)
229
if $self->dbo->_dbh->err;
230
}
231
2
51
$sth->finish;
232
233
2
39
1;
234
}
235
236
sub _update {
237
2
2
4
my $self = shift;
238
2
3
my ($fields, $id, $values, $where) = @_;
239
240
2
13
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
241
242
2
6
my $query = 'UPDATE '. $table. ' SET ';
243
2
11
$query .= $_. '=?, ' for @$fields;
244
2
9
$query =~ s/, $/ WHERE /;
245
2
100
7
if ($id) {
246
1
1
$query .= $id. '=?';
247
}
248
else {
249
1
4
$query .= $_. '=? AND ' for @$fields;
250
1
3
$query =~ s/ AND $//;
251
}
252
2
12
my $sth = $self->dbo->_dbh->prepare($query);
253
254
2
50
156
return $self->_carp('_update: prepare: query['.$query.']: '.
255
$self->dbo->_dbh->errstr)
256
if $self->dbo->_dbh->err;
257
258
2
45
for my $obj (@$values) {
259
2
2
my @fields;
260
2
12
push @fields, $obj->$_ for @$fields;
261
1
4
$id ? do { push @fields, $obj->$id }
262
2
100
39
: do { push @fields, $where->$_ for @$fields };
1
2
263
2
365
$sth->execute(@fields);
264
265
2
50
13
return $self->_carp('_update: execute: '.$self->dbo->_dbh->errstr)
266
if $self->dbo->_dbh->err;
267
}
268
2
47
$sth->finish;
269
270
2
22
1;
271
}
272
273
sub _insert {
274
4
4
8
my $self = shift;
275
4
9
my ($fields, $values) = @_;
276
277
4
36
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
278
279
4
11
my $query = 'INSERT INTO '. $table. '(';
280
4
19
$query .= $_. ', ' for @$fields;
281
4
22
$query =~ s/, $/) VALUES (/;
282
4
13
$query .= ('?, ' x scalar @$fields);
283
4
12
$query =~ s/, $/)/;
284
4
18
my $sth = $self->dbo->_dbh->prepare($query);
285
286
4
50
400
return $self->_carp('_insert: prepare: query['.$query.']: '.
287
$self->dbo->_dbh->errstr)
288
if $self->dbo->_dbh->err;
289
290
4
71
for my $obj (@$values) {
291
10
109
my @fields;
292
10
37
push @fields, $obj->$_ for @$fields;
293
10
660
$sth->execute(@fields);
294
295
10
50
30
return $self->_carp('_insert: execute: '.$self->dbo->_dbh->errstr)
296
if $self->dbo->_dbh->err;
297
}
298
4
80
$sth->finish;
299
300
4
49
1;
301
}
302
303
sub _select {
304
4
4
10
my $self = shift;
305
4
9
my (%fields) = @_;
306
307
4
33
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
308
309
4
14
my $query = 'SELECT * FROM '. $table. ' WHERE ';
310
4
100
16
if (%fields) {
311
1
3
do { $query .= $_. '=? AND ' } for keys %fields;
1
3
312
1
6
$query =~ s/ AND $//;
313
}
314
else {
315
3
57
$query =~ s/ WHERE $//;
316
}
317
318
4
24
my $sth = $self->dbo->_dbh->prepare($query);
319
320
4
50
470
return $self->_carp('_select: prepare: query['.$query.']: '.
321
$self->dbo->_dbh->errstr)
322
if $self->dbo->_dbh->err;
323
324
4
100
256
%fields
325
? $sth->execute(values %fields)
326
: $sth->execute;
327
328
4
50
18
return $self->_carp('_select: execute: '.$self->dbo->_dbh->errstr)
329
if $self->dbo->_dbh->err;
330
331
4
114
my $res = $sth->fetchall_arrayref({});
332
333
4
50
295
return $self->_carp('_select: fetchall_arrayref: '.$self->dbo->_dbh->errstr)
334
if $self->dbo->_dbh->err;
335
336
4
71
$sth->finish;
337
338
4
50
56
$self->can('_toObj')
339
? return $self->_toObj($res)
340
: return $res->[0];
341
}
342
343
sub _lookupId {
344
2
2
2
my $self = shift;
345
2
6
my ($id, %fields) = @_;
346
347
2
14
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
348
349
2
6
my $query = 'SELECT '. $id. ' FROM '. $table. ' WHERE ';
350
2
6
do { $query .= $_. '=? AND ' } for keys %fields;
2
6
351
2
10
$query =~ s/ AND $//;
352
353
2
10
my $sth = $self->dbo->_dbh->prepare($query);
354
355
2
50
227
return $self->_carp('_lookupId: prepare: query['.$query.']: '.
356
$self->dbo->_dbh->errstr)
357
if $self->dbo->_dbh->err;
358
359
2
158
$sth->execute(values %fields);
360
361
2
50
10
return $self->_carp('_lookupId: execute: '.$self->dbo->_dbh->errstr)
362
if $self->dbo->_dbh->err;
363
364
2
63
my @res = $sth->fetchrow_array;
365
366
2
50
7
return $self->_carp('_lookupId: fetchrow_array: '.$self->dbo->_dbh->errstr)
367
if $self->dbo->_dbh->err;
368
369
2
38
$sth->finish;
370
371
2
89
$res[0];
372
}
373
374
sub _lookupString {
375
2
2
4
my $self = shift;
376
2
4
my ($string, %fields) = @_;
377
378
2
15
my ($table) = ref($self) =~ /^(?:.*::)?(.*)/;
379
380
2
7
my $query = 'SELECT '. $string. ' FROM '. $table. ' WHERE ';
381
2
6
do { $query .= $_. '=? AND ' } for keys %fields;
2
6
382
2
8
$query =~ s/ AND $//;
383
384
2
6
my $sth = $self->dbo->_dbh->prepare($query);
385
386
2
50
162
return $self->_carp('_lookupString: prepare: query['.$query.']: '.
387
$self->dbo->_dbh->errstr)
388
if $self->dbo->_dbh->err;
389
390
2
141
$sth->execute(values %fields);
391
392
2
50
9
return $self->_carp('_lookupString: execute: '.$self->dbo->_dbh->errstr)
393
if $self->dbo->_dbh->err;
394
395
2
63
my @res = $sth->fetchrow_array;
396
397
2
50
7
return $self->_carp('_lookupString: fetchrow_array: '.
398
$self->dbo->_dbh->errstr)
399
if $self->dbo->_dbh->err;
400
401
2
31
$sth->finish;
402
403
2
55
$res[0];
404
}
405
406
# XXX: _lookupObject to return a list of objects
407
408
sub _toObj {
409
4
4
15
my $self = shift;
410
411
3
3
14
no strict 'refs';
3
7
3
276
412
4
6
my $id = ${ref($self). '::Id'};
4
13
413
4
5
my @fields = @{ref($self). '::Fields'};
4
18
414
415
4
100
24
$id ? return $self->__toObj([ $id, @fields ], @_)
416
: return $self->__toObj(\@fields, @_);
417
}
418
419
=item B
420
421
Method to create the table.
422
423
=cut
424
425
sub create {
426
2
2
1
62
my $self = shift;
427
428
3
3
13
no strict 'refs';
3
2
3
383
429
2
4
my $id = ${ref($self). '::Id'};
2
8
430
2
2
my @fields = @{ref($self). '::Fields'};
2
9
431
432
2
100
15
$id ? return $self->_create([ $id, @fields ], @_)
433
: return $self->_create(\@fields, 1, @_);
434
}
435
436
=item B
437
438
Method to verify existence of a table.
439
440
=cut
441
442
2
2
1
18
sub exists { shift->_exists(@_) }
443
444
=item B
445
446
If called without parameters, returns the whole content as an arrayref. If called with a hash as argument containing some table fields with values, it plays as multiple where clauses (return result as an arrayref also). See SYNOPSIS.
447
448
=cut
449
450
4
4
1
59977
sub select { shift->_select(@_) }
451
452
=item B
453
454
This method returns a reference to an array with each array indice set to the corresponding table object id.
455
456
=cut
457
458
sub selectById {
459
0
0
1
0
my $self = shift;
460
461
3
3
13
no strict 'refs';
3
4
3
250
462
0
0
my $id = ${ref($self). '::Id'};
0
0
463
464
0
0
my $sorted;
465
0
0
$sorted->[$_->$id] = $_ for @{$self->select(@_)};
0
0
466
0
0
$sorted;
467
}
468
469
=item B
470
471
Method used to generate a unique key, using to store and retrieve a database element quickly. By default, the key is the first field in the table schema (excluding the id field). It is user responsibility to override this method to use an appropriate key.
472
473
=cut
474
475
sub getKey {
476
0
0
1
0
my $self = shift;
477
478
3
3
13
no strict 'refs';
3
3
3
328
479
0
0
my @fields = @{ref($self). '::Fields'};
0
0
480
0
0
my $key = $fields[0];
481
482
0
0
$self->$key;
483
}
484
485
=item B
486
487
Method used to cache a table content. It uses B to store the object into a reference to a hash. You access a cached element by calling B on an object.
488
489
=cut
490
491
sub selectByKey {
492
0
0
1
0
my $self = shift;
493
0
0
my %cache = map { $_->getKey => $_ } @{$self->select(@_)};
0
0
0
0
494
0
0
\%cache;
495
}
496
497
=item B($arrayref)
498
499
Deletes all entries specified in the arrayref (they are all objects of type DBIx::SQLite::Simple::Table).
500
501
=cut
502
503
sub delete {
504
2
2
1
121969
my $self = shift;
505
506
3
3
16
no strict 'refs';
3
5
3
180
507
2
6
my @fields = @{ref($self). '::Fields'};
2
22
508
509
2
19
$self->_delete(\@fields, @_);
510
}
511
512
=item B($arrayref)
513
514
Insert all entries specified in the arrayref (they are all objects of type DBIx
515
::SQLite::Simple::Table).
516
517
=cut
518
519
sub insert {
520
4
4
1
25911
my $self = shift;
521
522
3
3
11
no strict 'refs';
3
4
3
235
523
4
8
my $id = ${ref($self). '::Id'};
4
20
524
4
4
my @fields = @{ref($self). '::Fields'};
4
21
525
526
4
100
34
$id ? return $self->_insert([ $id, @fields ], @_)
527
: return $self->_insert(\@fields, @_);
528
}
529
530
=item B($arrayref)
531
532
Will update elements specified within the arrayref (they are all objects of type DBIx::SQLite::Simple::Table). If an additionnal argument is passed, it will act as a where clause. See SYNOPSIS.
533
534
=cut
535
536
sub update {
537
2
2
1
45
my $self = shift;
538
539
3
3
12
no strict 'refs';
3
3
3
253
540
2
2
my $id = ${ref($self). '::Id'};
2
7
541
2
4
my @fields = @{ref($self). '::Fields'};
2
41
542
543
2
100
16
$id ? return $self->_update([ $id, @fields ], $id, @_)
544
: return $self->_update(\@fields, undef, @_);
545
}
546
547
=item B(%hash)
548
549
Returns the the id if the specified field/value hash.
550
551
=cut
552
553
sub lookupId {
554
2
2
1
5898
my $self = shift;
555
556
3
3
11
no strict 'refs';
3
3
3
219
557
2
3
my $id = ${ref($self). '::Id'};
2
8
558
559
2
9
$self->_lookupId($id, @_);
560
}
561
562
=item B($field, field2 => value)
563
564
Returns the content of the specified field. See SYNOPSIS.
565
566
=cut
567
568
2
2
1
5909
sub lookupString { shift->_lookupString(@_) }
569
570
=back
571
572
=head1 AUTHOR
573
574
Patrice EGomoRE Auffret
575
576
=head1 COPYRIGHT AND LICENSE
577
578
Copyright (c) 2005-2015, Patrice EGomoRE Auffret
579
580
You may distribute this module under the terms of the Artistic license.
581
See LICENSE.Artistic file in the source distribution archive.
582
583
=cut
584
585
1;