File Coverage

blib/lib/Class/DBI/DATA/Schema.pm
Criterion Covered Total %
statement 54 57 94.7
branch 11 22 50.0
condition 2 9 22.2
subroutine 10 10 100.0
pod n/a
total 77 98 78.5


line stmt bran cond sub pod time code
1             package Class::DBI::DATA::Schema;
2              
3             =head1 NAME
4              
5             Class::DBI::DATA::Schema - Execute Class::DBI SQL from DATA sections
6              
7             =head1 SYNOPSIS
8              
9             package Film.pm;
10             use base 'Class::DBI';
11             # ... normal Class::DBI setup
12              
13             use 'Class::DBI::DATA::Schema';
14              
15             Film->run_data_sql;
16              
17              
18             __DATA__
19             CREATE TABLE IF NOT EXISTS film (....);
20             REPLACE INTO film VALUES (...);
21             REPLACE INTO film VALUES (...);
22              
23             =head1 DESCRIPTION
24              
25             This is an extension to Class::DBI which injects a method into your class
26             to find and execute all SQL statements in the DATA section of the package.
27              
28             =cut
29              
30 1     1   1903 use strict;
  1         2  
  1         52  
31 1     1   7 use warnings;
  1         2  
  1         795  
32              
33             our $VERSION = '1.00';
34              
35             =head1 METHODS
36              
37             =head2 run_data_sql
38              
39             Film->run_data_sql;
40              
41             Using this module will export a run_data_sql method into your class.
42             This method will find SQL statements in the DATA section of the class
43             it is called from, and execute them against the database that that class
44             is set up to use.
45              
46             It is safe to import this method into a Class::DBI subclass being used
47             as the superclass for a range of classes.
48              
49             WARNING: this does not do anything fancy to work out what is SQL. It
50             merely assumes that everything in the DATA section is SQL, and
51             applies each thing it finds (separated by semi-colons) in turn to your
52             database. Similarly there is no security checking, or validation of the
53             DATA in any way.
54              
55             =head1 TRANSLATION and CACHING
56              
57             There are undocumented arguments that will allow this module to translate
58             the SQL from one database schema to another, and also to cache the result
59             of that translation. People are relying on these, so they're not going
60             to go away, but you're going to need to read the source and/or the tests
61             to work out how to use them.
62              
63             =cut
64              
65             sub import {
66 2     2   79448 my ($self, %args) = @_;
67 2         7 my $caller = caller();
68              
69 2         3 my $translating = 0;
70 2 100       10 if ($args{translate}) {
71 1     1   12 eval "use SQL::Translator";
  1         3  
  1         24  
  1         90  
72 1 50       6 $@ ? warn "Cannot translate without SQL::Translator" : ($translating = 1);
73             }
74              
75 2         4 my $CACHE = "";
76 2 50       8 if ($args{cache}) {
77 0         0 eval "use Cache::File; use Digest::MD5";
78 0 0 0     0 $@
      0        
79             ? warn "Cannot cache without Cache::File and Digest::MD5"
80             : (
81             $CACHE = Cache::File->new(
82             cache_root => $args{cache},
83             cache_umask => $args{cache_umask} || 000,
84             default_expires => $args{cache_duration} || '30 day',
85             ));
86             }
87              
88             my $translate = sub {
89 2     2   6 my $sql = shift;
90 2 50       5 if (my ($from, $to) = @{ $args{translate} || [] }) {
  2 50       20  
91 2 50       9 my $key = $CACHE ? Digest::MD5::md5_base64($sql.$from.$to) : "";
92 2 50       8 my $cached = $CACHE ? $CACHE->get($key) : "";
93 2 50       10 return $cached if $cached;
94              
95 2         91 my $translator = SQL::Translator->new(no_comments => 1, trace => 0);
96              
97             # Ahem.
98 2         2307 local $SIG{__WARN__} = sub { };
  1         122418  
99 2         11 local *Parse::RecDescent::_error = sub ($;$) { };
  0         0  
100 2   33     5 $sql = eval {
101             $translator->translate(
102             parser => $from,
103             producer => $to,
104             data => \$sql,
105             );
106             } || $sql;
107 2 50       2043747 $CACHE->set($key => $sql) if $CACHE;
108             }
109 2         38 $sql;
110 2         13 };
111              
112             my $transform = sub {
113 1     1   3 my $sql = shift;
114 1         16 return join ";", map $translate->("$_;"), grep /\S/, split /;/, $sql;
115 2         8 };
116              
117             my $get_statements = sub {
118 1     1   6 my $h = shift;
119 1         6 local $/ = undef;
120 1         45 chomp(my $sql = <$h>);
121 1 50       9 return grep /\S/, split /;/, $translating ? $transform->($sql) : $sql;
122 2         8 };
123              
124 2         3 my %cache;
125              
126 1     1   7 no strict 'refs';
  1         22  
  1         59  
127 2         44 *{"$caller\::run_data_sql"} = sub {
128 1     1   16506 my $class = shift;
129 1     1   6 no strict 'refs';
  1         2  
  1         120  
130 1   50     11 $cache{$class} ||= [ $get_statements->(*{"$class\::DATA"}{IO}) ];
  1         10  
131 1         5 $class->db_Main->do($_) foreach @{ $cache{$class} };
  1         13  
132 1         776530 return 1;
133             }
134              
135 2         8 }
136              
137             =head1 SEE ALSO
138              
139             L.
140              
141             =head1 AUTHOR
142              
143             Tony Bowden
144              
145             =head1 BUGS and QUERIES
146              
147             Please direct all correspondence regarding this module to:
148             bug-Class-DBI-DATA-Schema@rt.cpan.org
149              
150             =head1 COPYRIGHT
151              
152             Copyright (C) 2003-2005 Kasei
153              
154             This program is free software; you can redistribute it and/or modify it under
155             the terms of the GNU General Public License; either version 2 of the License,
156             or (at your option) any later version.
157              
158             This program is distributed in the hope that it will be useful, but WITHOUT
159             ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
160             FOR A PARTICULAR PURPOSE.
161              
162             =cut
163              
164             1;