File Coverage

blib/lib/ORLite.pm
Criterion Covered Total %
statement 345 379 91.0
branch 158 206 76.7
condition 25 39 64.1
subroutine 54 56 96.4
pod 1 2 50.0
total 583 682 85.4


line stmt bran cond sub pod time code
1             package ORLite;
2              
3             # See POD at end of file for documentation
4              
5 30     30   1022172 use 5.006;
  30         167  
  30         1120  
6 30     30   3455 use strict;
  30         101  
  30         855  
7 28     27   171 use Carp ();
  28         52  
  27         475  
8 27     27   135 use File::Spec 0.80 ();
  27         668  
  27         593  
9 27     27   142 use File::Path 2.08 ();
  27         641  
  27         5053  
10 27     27   168 use File::Basename ();
  27         54  
  27         565  
11 27     27   57944 use Params::Util 1.00 ();
  27         174816  
  27         792  
12 27     27   73557 use DBI 1.607 ();
  27         615821  
  27         1237  
13 27     27   37742 use DBD::SQLite 1.27 ();
  27         273294  
  27         922  
14              
15 27     27   511 use vars qw{$VERSION};
  27         490  
  27         8912  
16             BEGIN {
17 25     25   11479 $VERSION = '1.98';
18             }
19              
20             # Support for the 'prune' option
21             my @PRUNE = ();
22             END {
23 25     25   413840 foreach ( reverse @PRUNE ) {
24 0 50       0 next unless -e $_;
25 0         0 require File::Remove;
26 0         0 File::Remove::remove( \1, $_ );
27             }
28             }
29              
30              
31              
32              
33              
34             #####################################################################
35             # Code Generation
36              
37             sub import {
38 28   33 28   33661296 my $class = ref($_[0]) || $_[0];
39              
40             # Check for debug mode
41 28         94 my $DEBUG = 0;
42 28 50 66     403 if ( defined Params::Util::_STRING($_[-1]) and $_[-1] eq '-DEBUG' ) {
43 0         0 $DEBUG = 1;
44 0         0 pop @_;
45             }
46              
47             # Check params and apply defaults
48 28         444 my %params = (
49             # Simple defaults here, complex defaults later
50             package => scalar(caller),
51             create => 0,
52             cleanup => '',
53             array => 0,
54             xsaccessor => 0,
55             shim => 0,
56             tables => 1,
57             views => 0,
58             unicode => 0,
59             );
60 28 100       309 if ( defined Params::Util::_STRING($_[1]) ) {
    50          
61             # Support the short form "use ORLite 'db.sqlite'"
62 4         30 $params{file} = $_[1];
63             } elsif ( Params::Util::_HASHLIKE($_[1]) ) {
64 24         544 %params = ( %params, %{$_[1]} );
  24         284  
65             } else {
66 0         0 Carp::croak("Missing, empty or invalid params HASH");
67             }
68 28 50 66     988 unless (
      33        
69             defined Params::Util::_STRING($params{file})
70             and (
71             $params{create}
72             or
73             -f $params{file}
74             )
75             ) {
76 0         0 Carp::croak("Missing or invalid file param");
77             }
78 28 100       152 unless ( defined $params{readonly} ) {
79 26 100       656 $params{readonly} = $params{create} ? 0 : ! -w $params{file};
80             }
81 28 50       1711 unless ( Params::Util::_CLASS($params{package}) ) {
82 0         0 Carp::croak("Missing or invalid package class");
83             }
84              
85             # Check caching params
86 28         506 my $cached = undef;
87 28         87 my $pkg = $params{package};
88 28 100       138 if ( defined $params{cache} ) {
89             # Caching is illogical or invalid in some situations
90 2 50       7 if ( $params{prune} ) {
91 0         0 Carp::croak("Cannot set a 'cache' directory while 'prune' enabled");
92             }
93 2 50       6 unless ( $params{user_version} ) {
94 0         0 Carp::croak("Cannot set a 'cache' directory without 'user_version'");
95             }
96              
97             # To make the caching work, the version be defined before ORLite is called.
98 25     25   169 no strict 'refs';
  25         41  
  25         141587  
99 2 50       4 unless ( ${"$pkg\::VERSION"} ) {
  2         10  
100 0         0 Carp::croak("Cannot set a 'cache' directory without a package \$VERSION");
101             }
102              
103             # Build the cache file from the super path using an inlined Class::ISA
104 2         5 my @queue = ( $class );
105 2         135 my %seen = ( $pkg => 1 );
106 2         8 my @parts = ( $pkg => ${"$pkg\::VERSION"} );
  2         14  
107 2         37 while ( @queue ) {
108 2 50       9 my $c = Params::Util::_STRING(shift @queue) or next;
109 2         3 push @parts, $c => ${"$c\::VERSION"};
  2         7  
110 2         10 unshift @queue, grep { not $seen{$c}++ } @{"$c\::ISA"};
  0         0  
  2         14  
111             }
112 2         10 $cached = join '-', @parts, user_version => $params{user_version};
113 2         18 $cached =~ s/[:.-]+/-/g;
114 2         89 $cached = File::Spec->rel2abs(
115             File::Spec->catfile( $params{cache}, "$cached.pm" )
116             );
117             }
118              
119             # Create the parent directory if needed
120 28         1889 my $file = File::Spec->rel2abs($params{file});
121 28         611 my $created = ! -f $params{file};
122 28 100       453 if ( $created ) {
123 4         277 my $dir = File::Basename::dirname($file);
124 4 50       135 unless ( -d $dir ) {
125 0         0 my @dirs = File::Path::mkpath( $dir, { verbose => 0 } );
126 0 0       0 $class->prune(@dirs) if $params{prune};
127             }
128 4 50       19 $class->prune($file) if $params{prune};
129             }
130              
131             # Connect to the database
132 28         334 my $dsn = "dbi:SQLite:$file";
133 28 100       644 my $dbh = DBI->connect( $dsn, undef, undef, {
    100          
134             PrintError => 0,
135             RaiseError => 1,
136             ReadOnly => $params{create} ? 0 : 1,
137             $params{unicode} ? ( sqlite_unicode => 1 ) : ( ),
138             } );
139              
140             # Schema custom creation support
141 28 100 100     26805 if ( $created and Params::Util::_CODELIKE($params{create}) ) {
142 2         57 $params{create}->($dbh);
143             }
144              
145             # Check the schema version before generating
146 28         260756 my $user_version = $dbh->selectrow_arrayref('pragma user_version')->[0];
147 27 50 66     6517 if ( exists $params{user_version} and $user_version != $params{user_version} ) {
148 0         0 Carp::croak("Schema user_version mismatch (got $user_version, wanted $params{user_version})");
149             }
150              
151             # If caching and the cached version exists, load and shortcut.
152             # Don't try to catch exceptions, just let them blow up.
153 27 100 100     495 if ( $cached and -f $cached ) {
154 1         45 $dbh->disconnect;
155 1         4717 require $cached;
156 1         9083 return 1;
157             }
158              
159             # Prepare to generate code
160 26         226 my $cleanup = $params{cleanup};
161 26 100       122 my $readonly = $params{readonly} ? "\n\t\tReadOnly => 1," : '';
162 26 100       114 my $unicode = $params{unicode} ? "\n\t\tsqlite_unicode => 1," : '';
163 26 100       95 my $version = $unicode ? '5.008005' : '5.006';
164              
165             # Generate the support package code
166 26         493 my $code = <<"END_PERL";
167             package $pkg;
168              
169             use $version;
170             use strict;
171             use Carp ();
172             use DBI 1.607 ();
173             use DBD::SQLite 1.27 ();
174              
175             my \$DBH = undef;
176              
177             sub orlite { '$VERSION' }
178              
179             sub sqlite { '$file' }
180              
181             sub dsn { '$dsn' }
182              
183             sub dbh {
184             \$DBH or \$_[0]->connect;
185             }
186              
187             sub connect {
188             DBI->connect( \$_[0]->dsn, undef, undef, {
189             PrintError => 0,
190             RaiseError => 1,$readonly$unicode
191             } );
192             }
193              
194             sub connected {
195             defined \$DBH;
196             }
197              
198             sub prepare {
199             shift->dbh->prepare(\@_);
200             }
201              
202             sub do {
203             shift->dbh->do(\@_);
204             }
205              
206             sub selectall_arrayref {
207             shift->dbh->selectall_arrayref(\@_);
208             }
209              
210             sub selectall_hashref {
211             shift->dbh->selectall_hashref(\@_);
212             }
213              
214             sub selectcol_arrayref {
215             shift->dbh->selectcol_arrayref(\@_);
216             }
217              
218             sub selectrow_array {
219             shift->dbh->selectrow_array(\@_);
220             }
221              
222             sub selectrow_arrayref {
223             shift->dbh->selectrow_arrayref(\@_);
224             }
225              
226             sub selectrow_hashref {
227             shift->dbh->selectrow_hashref(\@_);
228             }
229              
230             sub pragma {
231             \$_[0]->do("pragma \$_[1] = \$_[2]") if \@_ > 2;
232             \$_[0]->selectrow_arrayref("pragma \$_[1]")->[0] if defined wantarray;
233             }
234              
235             sub iterate {
236             my \$class = shift;
237             my \$call = pop;
238             my \$sth = \$class->prepare(shift);
239             \$sth->execute(\@_);
240             while ( \$_ = \$sth->fetchrow_arrayref ) {
241             \$call->() or return 1;;
242             }
243             }
244              
245             sub begin {
246             \$DBH or
247             \$DBH = \$_[0]->connect;
248             \$DBH->begin_work;
249             }
250              
251             sub rollback {
252             \$DBH or return 1;
253             \$DBH->rollback;
254             \$DBH->disconnect;
255             undef \$DBH;
256             return 1;
257             }
258              
259             sub rollback_begin {
260             if ( \$DBH ) {
261             \$DBH->rollback;
262             \$DBH->begin_work;
263             } else {
264             \$_[0]->begin;
265             }
266             return 1;
267             }
268              
269             END_PERL
270              
271             # If you are a read-write database, we even allow you
272             # to commit your transactions.
273 26 100       144 $code .= <<"END_PERL" unless $readonly;
274             sub commit {
275             \$DBH or return 1;
276             \$DBH->commit;
277             \$DBH->disconnect;
278             undef \$DBH;
279             return 1;
280             }
281              
282             sub commit_begin {
283             if ( \$DBH ) {
284             \$DBH->commit;
285             \$DBH->begin_work;
286             } else {
287             \$_[0]->begin;
288             }
289             return 1;
290             }
291              
292             END_PERL
293              
294             # Cleanup and shutdown operations
295 26 100       110 if ( $cleanup ) {
296 2         12 $code .= <<"END_PERL";
297             END {
298             if ( \$DBH ) {
299             \$DBH->rollback;
300             \$DBH->do('$cleanup');
301             \$DBH->disconnect;
302             undef \$DBH;
303             } else {
304             $pkg->do('$cleanup');
305             }
306             }
307              
308             END_PERL
309             } else {
310 24         152 $code .= <<"END_PERL";
311             END {
312             $pkg->rollback if \$DBH;
313             }
314              
315             END_PERL
316             }
317              
318             # Optionally generate the table classes
319 26         55 my $tables = undef;
320 26 100       127 if ( $params{tables} ) {
321             # Capture the raw schema table information
322 23         503 $tables = $dbh->selectall_arrayref(
323             'select * from sqlite_master where name not like ? and type in ( ?, ? )',
324             { Slice => {} }, 'sqlite_%', 'table', 'view',
325             );
326              
327             # Capture the raw schema information and do first-pass work
328 23         16156 foreach my $t ( @$tables ) {
329             # Convenience pre-quoted form of the table name
330 35         368 $t->{qname} = $dbh->quote_identifier(undef, undef, $t->{name});
331              
332             # What will be the class for this table
333 35         3301 $t->{class} = $t->{name};
334 35 100       359 if ( $t->{class} ne lc $t->{class} ) {
335 1         10 $t->{class} =~ s/([a-z])([A-Z])/${1}_${2}/g;
336 1         5 $t->{class} =~ s/_+/_/g;
337             }
338 35         156 $t->{class} = ucfirst lc $t->{class};
339 35         229 $t->{class} =~ s/_([a-z])/uc($1)/ge;
  23         121  
340 35         134 $t->{class} = "${pkg}::$t->{class}";
341              
342             # Load the structural column list
343 35         453 my $columns = $t->{columns} = $dbh->selectall_arrayref(
344             "pragma table_info('$t->{name}')",
345             { Slice => {} },
346             );
347              
348             # The list of columns we will select, which can
349             # be different to the general list.
350 35         16763 my $select = $t->{select} = [ @$columns ];
351              
352             # Track array vs hash implementation on a per-table
353             # basis so that we can force views to always be done
354             # array-wise (to compensate for some weird SQLite
355             # column quoting differences between tables and views
356 35         110 $t->{array} = $params{array};
357 35 100       364 if ( $t->{type} eq 'view' ) {
358 4         11 $t->{array} = 1;
359             }
360              
361             # Track usage of rowid on a per-table basis because
362             # views don't always support rowid.
363 35         112 $t->{rowid} = $t->{type} eq 'table';
364              
365 35         89 foreach my $c ( @$select ) {
366             # Convenience escaping for the column names
367 82         497 $c->{qname} = $dbh->quote_identifier($c->{name});
368              
369             # Affinity detection
370 82 100 100     3976 if ( $c->{type} =~ /INT/i ) {
    100          
    100          
    100          
371 43         283 $c->{affinity} = 'INTEGER';
372             } elsif ( $c->{type} =~ /(?:CHAR|CLOB|TEXT)/i ) {
373 16         63 $c->{affinity} = 'TEXT';
374             } elsif ( $c->{type} =~ /BLOB/i or not $c->{type} ) {
375 2         6 $c->{affinity} = 'BLOB';
376              
377             # Unicode currently breaks BLOB columns
378 2 50       8 if ( $unicode ) {
379 0         0 die "BLOB column $t->{name}.$c->{name} is not supported in unicode database";
380             }
381             } elsif ( $c->{type} =~ /(?:REAL|FLOA|DOUB)/i ) {
382 1         6 $c->{affinity} = 'REAL';
383             } else {
384 20         188 $c->{affinity} = 'NUMERIC';
385             }
386             }
387              
388             # Analyze the primary keys structure
389 35         87 $t->{pk} = [ grep { $_->{pk} } @$columns ];
  82         229  
390 35         64 $t->{pkn} = scalar @{$t->{pk}};
  35         121  
391 35 100       140 if ( $t->{pkn} == 1 ) {
392 28         88 $t->{pk1} = $t->{pk}->[0];
393 28 100       119 if ( $t->{pk1}->{affinity} eq 'INTEGER' ) {
394 27         90 $t->{pki} = $t->{pk1};
395             }
396             }
397 35 100       154 if ( $t->{pki} ) {
    100          
398 27   33     192 $t->{rowid} &&= $t->{pki};
399 27 100       134 if ( $t->{pki}->{name} eq $t->{name} . '_id' ) {
400 3         14 $t->{id} = $t->{pki};
401             }
402              
403             } elsif ( $t->{rowid} ) {
404             # Add rowid to the query
405 4         31 $t->{rowid} = {
406             cid => -1,
407             name => 'rowid',
408             qname => '"rowid"',
409             type => 'integer',
410             affinity => 'INTEGER',
411             notnull => 1,
412             dflt_value => undef,
413             pk => 0,
414             };
415 4         315 push @$select, $t->{rowid};
416             }
417              
418             # Do we allow object creation?
419 35         154 $t->{create} = $t->{pkn};
420 35 100       136 $t->{create} = 1 if $t->{rowid};
421 35 100       105 $t->{create} = 0 if $readonly;
422              
423             # Generate the object keys for the columns
424 35 100       505 if ( $t->{array} ) {
425 15         56 foreach my $i ( 0 .. $#$select ) {
426 40         101 $select->[$i]->{xs} = $i;
427 40         154 $select->[$i]->{key} = "[$i]";
428             }
429             } else {
430 20         61 foreach my $c ( @$select ) {
431 46         132 $c->{xs} = "'$c->{name}'";
432 46         136 $c->{key} = "{$c->{name}}";
433             }
434             }
435              
436             # Generate the main SQL fragments
437 35         102 $t->{sql_scols} = join ', ', map { $_->{qname} } @$select;
  86         284  
438 35         81 $t->{sql_icols} = join ', ', map { $_->{qname} } @$columns;
  82         253  
439 35         159 $t->{sql_ivals} = join ', ', ( '?' ) x scalar @$columns;
440 35         156 $t->{sql_select} = "select $t->{sql_scols} from $t->{qname}";
441 35         483 $t->{sql_insert} =
442             "insert into $t->{qname} " .
443             "( $t->{sql_icols} ) " .
444             "values ( $t->{sql_ivals} )";
445 32         166 $t->{sql_where} = join ' and ',
446 35         84 map { "$_->{qname} = ?" } @{$t->{pk}};
  35         96  
447              
448             # Generate the new Perl fragments
449 82 100       456 $t->{pl_new} = join "\n", map {
450 35         90 $t->{array}
451             ? "\t\t\$attr{$_->{name}},"
452             : "\t\t$_->{name} => \$attr{$_->{name}},"
453             } @$columns;
454              
455 82         293 $t->{pl_insert} = join "\n", map {
456 35         97 "\t\t\$self->$_->{key},"
457             } @$columns;
458              
459 35         102 $t->{pl_fill} = '';
460 35 100       172 if ( $t->{pki} ) {
    100          
461 27         194 $t->{pl_fill} =
462             "\t\$self->$t->{pki}->{key} " .
463             "= \$dbh->func('last_insert_rowid') " .
464             "unless \$self->$t->{pki}->{key};";
465             } elsif ( $t->{rowid} ) {
466 4         24 $t->{pl_fill} =
467             "\t\$self->$t->{rowid}->{key} " .
468             "= \$dbh->func('last_insert_rowid');";
469             }
470             }
471              
472             # Generate the foreign key metadata
473 23         60 my %tindex = map { $_->{name} => $_ } @$tables;
  35         163  
474 23         64 foreach my $t ( @$tables ) {
475             # Locate the foreign keys
476 35         67 my %fk = ();
477 35         155 my @fk_sql = $t->{sql} =~ /[(,]\s*(.+?REFERENCES.+?)\s*[,)]/g;
478              
479             # Extract the details
480 35         93 foreach ( @fk_sql ) {
481 4 50       33 unless ( /^(\w+).+?REFERENCES\s+(\w+)\s*\(\s*(\w+)/ ) {
482 0         0 die "Invalid foreign key $_";
483             }
484 4         34 $fk{"$1"} = [ "$2", $tindex{"$2"}, "$3" ];
485             }
486 35         66 foreach ( @{$t->{columns}} ) {
  35         90  
487 82         207 $_->{fk} = $fk{$_->{name}};
488             }
489              
490             # One final code fragment we need the fk for
491 78         415 $t->{pl_accessor} = join "\n",
492 82         184 map { "\t\t$_->{name} => $_->{xs}," }
493 35         74 grep { ! $_->{fk} } @{$t->{columns}};
  35         82  
494             }
495              
496             # Generate the per-table code
497 23         157 foreach my $t ( @$tables ) {
498 35         52 my @select = @{$t->{select}};
  35         113  
499 35         53 my @columns = @{$t->{columns}};
  35         598  
500 35 100       132 my $slice = $t->{array}
501             ? '{}'
502             : '{ Slice => {} }';
503              
504             # Generate the package header
505 35 100       102 if ( $params{shim} ) {
506             # Generate a shim-wrapper class
507 1         8 $code .= <<"END_PERL";
508             package $t->{class};
509              
510             \@$t->{class}::ISA = '$t->{class}::Shim';
511              
512             package $t->{class}::Shim;
513              
514             END_PERL
515             } else {
516             # Plain vanilla package header
517 34         133 $code .= <<"END_PERL";
518             package $t->{class};
519              
520             END_PERL
521             }
522              
523             # Generate the common elements for all classes
524 35         375 $code .= <<"END_PERL";
525             sub base { '$pkg' }
526              
527             sub table { '$t->{name}' }
528              
529             sub table_info {
530             $pkg->selectall_arrayref(
531             "pragma table_info('$t->{name}')",
532             { Slice => {} },
533             );
534             }
535              
536             sub select {
537             my \$class = shift;
538             my \$sql = '$t->{sql_select} ';
539             \$sql .= shift if \@_;
540             my \$rows = $pkg->selectall_arrayref( \$sql, $slice, \@_ );
541             bless \$_, '$t->{class}' foreach \@\$rows;
542             wantarray ? \@\$rows : \$rows;
543             }
544              
545             sub count {
546             my \$class = shift;
547             my \$sql = 'select count(*) from $t->{qname} ';
548             \$sql .= shift if \@_;
549             $pkg->selectrow_array( \$sql, {}, \@_ );
550             }
551              
552             END_PERL
553              
554             # Handle different versions, because arrayref acts funny
555 35 100       137 if ( $t->{array} ) {
556 15         72 $code .= <<"END_PERL";
557             sub iterate {
558             my \$class = shift;
559             my \$call = pop;
560             my \$sql = '$t->{sql_select} ';
561             \$sql .= shift if \@_;
562             my \$sth = $pkg->prepare(\$sql);
563             \$sth->execute(\@_);
564             while ( \$_ = \$sth->fetchrow_arrayref ) {
565             \$_ = bless [ \@\$_ ], '$t->{class}';
566             \$call->() or last;
567             }
568             \$sth->finish;
569             }
570              
571             END_PERL
572             } else {
573 20         136 $code .= <<"END_PERL";
574             sub iterate {
575             my \$class = shift;
576             my \$call = pop;
577             my \$sql = '$t->{sql_select} ';
578             \$sql .= shift if \@_;
579             my \$sth = $pkg->prepare(\$sql);
580             \$sth->execute(\@_);
581             while ( \$_ = \$sth->fetchrow_hashref ) {
582             bless \$_, '$t->{class}';
583             \$call->() or last;
584             }
585             \$sth->finish;
586             }
587              
588             END_PERL
589             }
590              
591             # Add the primary key based single object loader
592 35 100       736 if ( $t->{pkn} ) {
593 30 100       97 if ( $t->{array} ) {
594 10         51 $code .= <<"END_PERL";
595             sub load {
596             my \$class = shift;
597             my \@row = $pkg->selectrow_array(
598             '$t->{sql_select} where $t->{sql_where}',
599             undef, \@_,
600             );
601             unless ( \@row ) {
602             Carp::croak("$t->{class} row does not exist");
603             }
604             bless \\\@row, '$t->{class}';
605             }
606              
607             END_PERL
608             } else {
609 20         304 $code .= <<"END_PERL";
610             sub load {
611             my \$class = shift;
612             my \$row = $pkg->selectrow_hashref(
613             '$t->{sql_select} where $t->{sql_where}',
614             undef, \@_,
615             );
616             unless ( \$row ) {
617             Carp::croak("$t->{class} row does not exist");
618             }
619             bless \$row, '$t->{class}';
620             }
621              
622             END_PERL
623             }
624             }
625              
626             # Generate the elements for tables with primary keys
627 35 100       113 if ( $t->{create} ) {
628 30 100       233 my $l = $t->{array} ? '[' : '{';
629 30 100       244 my $r = $t->{array} ? ']' : '}';
630 30 100       94 my $set = $t->{array}
631             ? '$self->set( $_ => $set{$_} ) foreach keys %set;'
632             : '$self->{$_} = $set{$_} foreach keys %set;';
633 30         502 $code .= <<"END_PERL";
634             sub new {
635             my \$class = shift;
636             my \%attr = \@_;
637             bless $l
638             $t->{pl_new}
639             $r, \$class;
640             }
641              
642             sub create {
643             shift->new(\@_)->insert;
644             }
645              
646             sub insert {
647             my \$self = shift;
648             my \$dbh = $pkg->dbh;
649             \$dbh->do(
650             '$t->{sql_insert}',
651             {},
652             $t->{pl_insert}
653             );
654             $t->{pl_fill}
655             return \$self;
656             }
657              
658             sub update {
659             my \$self = shift;
660             my \%set = \@_;
661             my \$rows = $pkg->do(
662             'update $t->{qname} set ' .
663             join( ', ', map { "\\"\$_\\" = ?" } keys \%set ) .
664             ' where "rowid" = ?',
665             {},
666             values \%set,
667             \$self->rowid,
668             );
669             unless ( \$rows == 1 ) {
670             Carp::croak("Expected to update 1 row, actually updated \$rows");
671             }
672             $set
673             return 1;
674             }
675              
676             sub delete {
677             return $pkg->do(
678             'delete from $t->{qname} where "rowid" = ?', {},
679             shift->rowid,
680             ) if ref \$_[0];
681             Carp::croak("Static $pkg->delete has been deprecated");
682             }
683              
684             sub delete_where {
685             shift; $pkg->do('delete from $t->{qname} where ' . shift, {}, \@_);
686             }
687              
688             sub truncate {
689             $pkg->do('delete from $t->{qname}');
690             }
691              
692             END_PERL
693             }
694              
695 35 100 100     281 if ( $t->{create} and $t->{array} ) {
696             # Add an additional set method to avoid having
697             # the user have to enter manual positions.
698 11         69 $code .= <<"END_PERL";
699             sub set {
700             my \$self = shift;
701             my \$i = {
702             $t->{pl_accessor}
703             }->{\$_[0]};
704             Carp::croak("Bad name '\$_[0]'") unless defined \$i;
705             \$self->[\$i] = \$_[1];
706             }
707              
708             END_PERL
709             }
710              
711             # Generate the boring accessors
712 35 100       108 if ( $params{xsaccessor} ) {
713 4 50       10 my $type = $t->{create} ? 'accessors' : 'getters';
714 4 100       10 my $xsclass = $t->{array}
715             ? 'Class::XSAccessor::Array'
716             : 'Class::XSAccessor';
717 4 50       11 my $id = $t->{id}
718             ? "\t\t$t->{id}->{name} => $t->{id}->{xs},\n"
719             : '';
720 4 50 33     17 my $rowid = ($t->{id} and $t->{rowid})
721             ? "\t\t$t->{rowid}->{name} => $t->{rowid}->{xs},\n"
722             : '';
723              
724 4         26 $code .= <<"END_PERL";
725             use $xsclass 1.05 {
726             getters => {
727             ${rowid}${id}$t->{pl_accessor}
728             },
729             };
730              
731             END_PERL
732             } else {
733 31 100 66     195 if ( $t->{pki} and $t->{rowid} ) {
734 23         147 $code .= <<"END_PERL";
735             sub rowid {
736             \$_[0]->$t->{rowid}->{key};
737             }
738              
739             END_PERL
740             }
741              
742 31 100       113 if ( $t->{id} ) {
743 3         17 $code .= <<"END_PERL";
744             sub id {
745             \$_[0]->$t->{id}->{key};
746             }
747              
748             END_PERL
749             }
750              
751 31         73 $code .= join "\n\n", map { <<"END_PERL" } grep { ! $_->{fk} } @select;
  76         275  
  78         190  
752             sub $_->{name} {
753             \$_[0]->$_->{key};
754             }
755             END_PERL
756             }
757              
758             # Generate the foreign key accessors
759 35         84 $code .= join "\n\n", map { <<"END_PERL" } grep { $_->{fk} } @columns;
  4         127  
  82         233  
760             sub $_->{name} {
761             ($_->{fk}->[1]->{class}\->select('where \"$_->{fk}->[1]->{pk}->[0]->{name}\" = ?', \$_[0]->$_->{key}))[0];
762             }
763             END_PERL
764             }
765             }
766              
767             # We are finished with the database
768 26         1775 $dbh->disconnect;
769              
770             # Start the post-table content again
771 26 100       203 $code .= "\npackage $pkg;\n" if $params{tables};
772              
773             # Append any custom code for the user
774 26 100       124 $code .= "\n$params{append}" if defined $params{append};
775              
776             # Load the overload classes for each of the tables
777 26 100       103 if ( $tables ) {
778 35         183 $code .= join( "\n",
779             "local \$@ = undef;",
780             map {
781 23         95 "eval { require $_->{class} };"
782             } @$tables
783             );
784             }
785              
786             # End the class normally
787 26         65 $code .= "\n\n1;\n";
788              
789             # Save to the cache location if caching is enabled
790 26 100       94 if ( $cached ) {
791 1         77 my $dir = File::Basename::dirname($cached);
792 1 50       23 unless ( -d $dir ) {
793 0         0 File::Path::mkpath( $dir, { verbose => 0 } );
794             }
795              
796             # Save a copy of the code to the file
797 1         4 local *FILE;
798 1 50       134 open( FILE, ">$cached" ) or Carp::croak("open($cached): $!");
799 1         8 print FILE $code;
800 1         159 close FILE;
801             }
802              
803             # Compile the code
804 26         61 local $@;
805 26 50 33     1148 if ( $^P and $^V >= 5.008009 ) {
    0          
806 26         130 local $^P = $^P | 0x800;
807 26 100   79   3892 eval($code);
  39 50   61   1851  
  24 50   36   90  
  24 100   22   1550  
  24 100   215   180  
  24 50   41   849  
  215 100   39   1915  
  43 100   42   6163  
  58 100   200   288309  
  58 100   22   682  
  58 100   5   500  
  58 100   25   970  
  62 100   192   86738  
  234 50   46   5154  
  56 50   19   72458  
  36 100   7   79554  
  24 100   21   101934  
  3 100   26   73  
  28 100   16   147  
  192 0   9   35748  
  48 0   15   4484  
  40 0   18   5957  
  29 0   1   11694  
  29 50   20   1501868  
  29 50   26   5067  
  9 0   67   1563  
  8 0   2   30  
  8 50   3   2314  
  8 50   52   157829  
  8     17   770  
  6     16   1951  
  8     6   60  
  10     2   1156  
  10     3   78131  
  8     8   2117  
  5     8   41  
  5     1   2060  
  3     0   643  
  5     0   21092  
  5     1   156  
  2         263  
  19         16642  
  19         196  
  19         23190  
  7         2361  
  16         133  
  29         5327  
  29         188  
  33         722  
  17         84  
  20         3012  
  22         258  
  16         1948  
  12         5735  
  19         165228  
  20         7794578  
  9         27  
  9         302  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  19         992  
  25         64001  
  25         2372  
  22         1180  
  21         144  
  21         38854  
  21         298  
  62         16601  
  19         45  
  21         112  
  70         662  
  36         22405  
  34         431  
  6         311  
  2         11  
  3         23  
  8         6513  
  8         1748  
  4         19  
  4         27  
  4         44  
  4         54022  
  0         0  
  3         34  
  3         32  
  2         599  
  2         8  
  2         9  
  2         15  
  2         18356  
  1         9  
  1         12  
  1         12  
  0         0  
  1         7  
  1         6  
  1         8  
  2         14  
  2         8  
  2         12  
  1         7  
  1         1301  
  1         10  
  0            
  0            
  0            
  0            
  0            
  0            
808 26 50       219 die $@ if $@;
809             } elsif ( $DEBUG ) {
810 0         0 dval($code);
811             } else {
812 0         0 eval($code);
813 0 0       0 die $@ if $@;
814             }
815              
816 26         4402 return 1;
817             }
818              
819             sub dval {
820             # Write the code to the temp file
821 5     5 0 7534 require File::Temp;
822 15         15028 my ($fh, $filename) = File::Temp::tempfile();
823 19         17606 $fh->print($_[0]);
824 34         33493 close $fh;
825 39         10959 require $filename;
826 14         3449 unlink $filename;
827              
828             # Print the debugging output
829             # my @trace = map {
830             # s/\s*[{;]$//;
831             # s/^s/ s/;
832             # s/^p/\np/;
833             # "$_\n"
834             # } grep {
835             # /^(?:package|sub)\b/
836             # } split /\n/, $_[0];
837             # print STDERR @trace, "\nCode saved as $filename\n\n";
838              
839 4         68720 return 1;
840             }
841              
842             sub prune {
843 4     15 1 352 my $class = shift;
844 4         24 push @PRUNE, map { File::Spec->rel2abs($_) } @_;
  4         402  
845             }
846              
847             1;
848              
849             __END__