File Coverage

blib/lib/Wiki/Toolkit/Setup/SQLite.pm
Criterion Covered Total %
statement 15 101 14.8
branch 0 46 0.0
condition 0 21 0.0
subroutine 5 12 41.6
pod 2 3 66.6
total 22 183 12.0


line stmt bran cond sub pod time code
1             package Wiki::Toolkit::Setup::SQLite;
2              
3 4     4   2004 use strict;
  4         4  
  4         104  
4              
5 4     4   12 use vars qw( @ISA $VERSION $SCHEMA_VERSION );
  4         6  
  4         175  
6              
7 4     4   680 use Wiki::Toolkit::Setup::Database;
  4         7  
  4         137  
8              
9             @ISA = qw( Wiki::Toolkit::Setup::Database );
10             $VERSION = '0.10';
11              
12 4     4   2757 use DBI;
  4         25032  
  4         172  
13 4     4   20 use Carp;
  4         4  
  4         3840  
14              
15             $SCHEMA_VERSION = $VERSION*100;
16              
17             my $create_sql = {
18             8 => {
19             schema_info => [ qq|
20             CREATE TABLE schema_info (
21             version integer NOT NULL default 0
22             );
23             |, qq|
24             INSERT INTO schema_info VALUES (8)
25             | ],
26             node => [ qq|
27             CREATE TABLE node (
28             id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
29             name varchar(200) NOT NULL DEFAULT '',
30             version integer NOT NULL default 0,
31             text mediumtext NOT NULL default '',
32             modified datetime default NULL
33             )
34             | ],
35             content => [ qq|
36             CREATE TABLE content (
37             node_id integer NOT NULL,
38             version integer NOT NULL default 0,
39             text mediumtext NOT NULL default '',
40             modified datetime default NULL,
41             comment mediumtext NOT NULL default '',
42             PRIMARY KEY (node_id, version)
43             )
44             | ],
45             internal_links => [ qq|
46             CREATE TABLE internal_links (
47             link_from varchar(200) NOT NULL default '',
48             link_to varchar(200) NOT NULL default '',
49             PRIMARY KEY (link_from, link_to)
50             )
51             | ],
52             metadata => [ qq|
53             CREATE TABLE metadata (
54             node_id integer NOT NULL,
55             version integer NOT NULL default 0,
56             metadata_type varchar(200) NOT NULL DEFAULT '',
57             metadata_value mediumtext NOT NULL DEFAULT ''
58             )
59             | ]
60             },
61             9 => {
62             schema_info => [ qq|
63             CREATE TABLE schema_info (
64             version integer NOT NULL default 0
65             );
66             |, qq|
67             INSERT INTO schema_info VALUES (9)
68             | ],
69              
70             node => [ qq|
71             CREATE TABLE node (
72             id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
73             name varchar(200) NOT NULL DEFAULT '',
74             version integer NOT NULL default 0,
75             text mediumtext NOT NULL default '',
76             modified datetime default NULL,
77             moderate boolean NOT NULL default '0'
78             )
79             | ],
80             content => [ qq|
81             CREATE TABLE content (
82             node_id integer NOT NULL,
83             version integer NOT NULL default 0,
84             text mediumtext NOT NULL default '',
85             modified datetime default NULL,
86             comment mediumtext NOT NULL default '',
87             moderated boolean NOT NULL default '1',
88             PRIMARY KEY (node_id, version)
89             )
90             | ],
91             internal_links => [ qq|
92             CREATE TABLE internal_links (
93             link_from varchar(200) NOT NULL default '',
94             link_to varchar(200) NOT NULL default '',
95             PRIMARY KEY (link_from, link_to)
96             )
97             | ],
98             metadata => [ qq|
99             CREATE TABLE metadata (
100             node_id integer NOT NULL,
101             version integer NOT NULL default 0,
102             metadata_type varchar(200) NOT NULL DEFAULT '',
103             metadata_value mediumtext NOT NULL DEFAULT ''
104             )
105             | ]
106             },
107             10 => {
108             schema_info => [ qq|
109             CREATE TABLE schema_info (
110             version integer NOT NULL default 0
111             );
112             |, qq|
113             INSERT INTO schema_info VALUES (10)
114             | ],
115              
116             node => [ qq|
117             CREATE TABLE node (
118             id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
119             name varchar(200) NOT NULL DEFAULT '',
120             version integer NOT NULL default 0,
121             text mediumtext NOT NULL default '',
122             modified datetime default NULL,
123             moderate boolean NOT NULL default '0'
124             )
125             |, qq|
126             CREATE UNIQUE INDEX node_name ON node (name)
127             | ],
128             content => [ qq|
129             CREATE TABLE content (
130             node_id integer NOT NULL,
131             version integer NOT NULL default 0,
132             text mediumtext NOT NULL default '',
133             modified datetime default NULL,
134             comment mediumtext NOT NULL default '',
135             moderated boolean NOT NULL default '1',
136             verified datetime default NULL,
137             verified_info mediumtext NOT NULL default '',
138             PRIMARY KEY (node_id, version)
139             )
140             | ],
141             internal_links => [ qq|
142             CREATE TABLE internal_links (
143             link_from varchar(200) NOT NULL default '',
144             link_to varchar(200) NOT NULL default '',
145             PRIMARY KEY (link_from, link_to)
146             )
147             | ],
148             metadata => [ qq|
149             CREATE TABLE metadata (
150             node_id integer NOT NULL,
151             version integer NOT NULL default 0,
152             metadata_type varchar(200) NOT NULL DEFAULT '',
153             metadata_value mediumtext NOT NULL DEFAULT ''
154             )
155             | ]
156             },
157             };
158              
159             my %fetch_upgrades = (
160             old_to_8 => 1,
161             old_to_9 => 1,
162             old_to_10 => 1,
163             '8_to_9' => 1,
164             '8_to_10' => 1,
165             '9_to_10' => 1,
166             );
167              
168             my %upgrades = ();
169              
170             =head1 NAME
171              
172             Wiki::Toolkit::Setup::SQLite - Set up tables for a Wiki::Toolkit store in a SQLite database.
173              
174             =head1 SYNOPSIS
175              
176             use Wiki::Toolkit::Setup::SQLite;
177             Wiki::Toolkit::Setup::SQLite::setup( $dbfile );
178              
179             =head1 DESCRIPTION
180              
181             Set up a SQLite database for use as a Wiki::Toolkit store.
182              
183             =head1 FUNCTIONS
184              
185             =over 4
186              
187             =item B
188              
189             use Wiki::Toolkit::Setup::SQLite;
190              
191             Wiki::Toolkit::Setup::SQLite::setup( $filename );
192              
193             or
194              
195             Wiki::Toolkit::Setup::SQLite::setup( $dbh );
196              
197             Takes one argument - B the name of the file that the SQLite
198             database is stored in B an active database handle.
199              
200             B If a table that the module wants to create already exists,
201             C will leave it alone. This means that you can safely run this
202             on an existing L database to bring the schema up to date
203             with the current L version. If you wish to completely start
204             again with a fresh database, run C first.
205              
206             An optional second argument may be passed specifying the schema version
207             to use; this is B intended to be used during unit testing and should
208             not normally be specified.
209              
210             =cut
211              
212             sub setup {
213 0     0 1   my @args = @_;
214 0           my $dbh = _get_dbh( @args );
215 0           my $disconnect_required = _disconnect_required( @args );
216 0   0       my $wanted_schema = _get_wanted_schema( @args ) || $SCHEMA_VERSION;
217              
218             die "No schema information for requested schema version $wanted_schema\n"
219 0 0         unless $create_sql->{$wanted_schema};
220              
221             # Check whether tables exist, set them up if not.
222 0           my %tables = fetch_tables_listing($dbh, $wanted_schema);
223              
224             # Do we need to upgrade the schema?
225             # (Don't check if no tables currently exist)
226 0           my $upgrade_schema;
227             my @cur_data;
228 0 0         if(scalar keys %tables > 0) {
229 0           $upgrade_schema = Wiki::Toolkit::Setup::Database::get_database_upgrade_required($dbh,$wanted_schema);
230             }
231 0 0         if($upgrade_schema) {
232 0 0         if ($fetch_upgrades{$upgrade_schema}) {
233             # Grab current data
234 0           print "Upgrading: $upgrade_schema\n";
235 0           @cur_data = eval("&Wiki::Toolkit::Setup::Database::fetch_upgrade_".$upgrade_schema."(\$dbh)");
236              
237             # Drop the current tables
238 0           cleardb($dbh);
239              
240             # Grab new list of tables
241 0           %tables = fetch_tables_listing($dbh, $wanted_schema);
242             }
243             }
244              
245             # Set up tables if not found
246 0           foreach my $required ( keys %{$create_sql->{$wanted_schema}} ) {
  0            
247 0 0         if ( $tables{$required} ) {
248 0           print "Table $required already exists... skipping...\n";
249             } else {
250 0           print "Creating table $required... done\n";
251 0           foreach my $sql (@{$create_sql->{$wanted_schema}->{$required}} ) {
  0            
252 0 0         $dbh->do($sql) or croak $dbh->errstr;
253             }
254             }
255             }
256              
257             # If upgrading, load in the new data
258 0 0         if($upgrade_schema) {
259 0 0         if ($fetch_upgrades{$upgrade_schema}) {
260 0           Wiki::Toolkit::Setup::Database::bulk_data_insert($dbh,@cur_data);
261             } else {
262 0           print "Upgrading schema: $upgrade_schema\n";
263 0           my @updates = @{$upgrades{$upgrade_schema}};
  0            
264 0           foreach my $update (@updates) {
265 0 0         if(ref($update) eq "CODE") {
    0          
266 0           &$update($dbh);
267             } elsif(ref($update) eq "ARRAY") {
268 0           foreach my $nupdate (@$update) {
269 0           $dbh->do($nupdate);
270             }
271             } else {
272 0           $dbh->do($update);
273             }
274             }
275             }
276             }
277              
278             # Clean up if we made our own dbh.
279 0 0         $dbh->disconnect if $disconnect_required;
280             }
281              
282             # Internal method - what tables are defined?
283             sub fetch_tables_listing {
284 0     0 0   my $dbh = shift;
285 0           my $wanted_schema = shift;
286              
287             # Check whether tables exist, set them up if not.
288             my $sql = "SELECT name FROM sqlite_master
289             WHERE type='table' AND name in ("
290 0           . join( ",", map { $dbh->quote($_) } keys %{$create_sql->{$wanted_schema}} ) . ")";
  0            
  0            
291 0 0         my $sth = $dbh->prepare($sql) or croak $dbh->errstr;
292 0           $sth->execute;
293 0           my %tables;
294 0           while ( my $table = $sth->fetchrow_array ) {
295 0           $tables{$table} = 1;
296             }
297 0           return %tables;
298             }
299              
300             =item B
301              
302             use Wiki::Toolkit::Setup::SQLite;
303              
304             # Clear out all Wiki::Toolkit tables from the database.
305             Wiki::Toolkit::Setup::SQLite::cleardb( $filename );
306              
307             or
308              
309             Wiki::Toolkit::Setup::SQLite::cleardb( $dbh );
310              
311             Takes one argument - B the name of the file that the SQLite
312             database is stored in B an active database handle.
313              
314             Clears out all L store tables from the database. B
315             that this will lose all your data; you probably only want to use this
316             for testing purposes or if you really screwed up somewhere. Note also
317             that it doesn't touch any L search backend tables; if you
318             have any of those in the same or a different database see
319             L or L, depending on
320             which search backend you're using.
321              
322             =cut
323              
324             sub cleardb {
325 0     0 1   my @args = @_;
326 0           my $dbh = _get_dbh( @args );
327 0           my $disconnect_required = _disconnect_required( @args );
328              
329 0           print "Dropping tables... ";
330             my $sql = "SELECT name FROM sqlite_master
331             WHERE type='table' AND name in ("
332 0           . join( ",", map { $dbh->quote($_) } keys %{$create_sql->{$SCHEMA_VERSION}} ) . ")";
  0            
  0            
333 0           foreach my $tableref (@{$dbh->selectall_arrayref($sql)}) {
  0            
334 0 0         $dbh->do("DROP TABLE $tableref->[0]") or croak $dbh->errstr;
335             }
336 0           print "done\n";
337              
338             # Clean up if we made our own dbh.
339 0 0         $dbh->disconnect if $disconnect_required;
340             }
341              
342             sub _get_dbh {
343             # Database handle passed in.
344 0 0 0 0     if ( ref $_[0] and ref $_[0] eq 'DBI::db' ) {
345 0           return $_[0];
346             }
347              
348             # Args passed as hashref.
349 0 0 0       if ( ref $_[0] and ref $_[0] eq 'HASH' ) {
350 0           my %args = %{$_[0]};
  0            
351 0 0         if ( $args{dbh} ) {
352 0           return $args{dbh};
353             } else {
354 0           return _make_dbh( %args );
355             }
356             }
357              
358             # Args passed as list of connection details.
359 0           return _make_dbh( dbname => $_[0] );
360             }
361              
362             sub _get_wanted_schema {
363             # Database handle passed in.
364 0 0 0 0     if ( ref $_[0] and ref $_[0] eq 'DBI::db' ) {
365 0           return undef;
366             }
367              
368             # Args passed as hashref.
369 0 0 0       if ( ref $_[0] and ref $_[0] eq 'HASH' ) {
370 0           my %args = %{$_[0]};
  0            
371 0           return $args{wanted_schema};
372             }
373             }
374              
375             sub _disconnect_required {
376             # Database handle passed in.
377 0 0 0 0     if ( ref $_[0] and ref $_[0] eq 'DBI::db' ) {
378 0           return 0;
379             }
380              
381             # Args passed as hashref.
382 0 0 0       if ( ref $_[0] and ref $_[0] eq 'HASH' ) {
383 0           my %args = %{$_[0]};
  0            
384 0 0         if ( $args{dbh} ) {
385 0           return 0;
386             } else {
387 0           return 1;
388             }
389             }
390              
391             # Args passed as list of connection details.
392 0           return 1;
393             }
394              
395             sub _make_dbh {
396 0     0     my %args = @_;
397 0 0         my $dbh = DBI->connect("dbi:SQLite:dbname=$args{dbname}", "", "",
398             { PrintError => 1, RaiseError => 1,
399             AutoCommit => 1 } )
400             or croak DBI::errstr;
401 0           return $dbh;
402             }
403              
404             =back
405              
406             =head1 ALTERNATIVE CALLING SYNTAX
407              
408             As requested by Podmaster. Instead of passing arguments to the methods as
409              
410             ($filename)
411              
412             you can pass them as
413              
414             ( { dbname => $filename } )
415              
416             or indeed
417              
418             ( { dbh => $dbh } )
419              
420             Note that's a hashref, not a hash.
421              
422             =head1 AUTHOR
423              
424             Kake Pugh (kake@earth.li).
425              
426             =head1 COPYRIGHT
427              
428             Copyright (C) 2002-2004 Kake Pugh. All Rights Reserved.
429             Copyright (C) 2006-2009 the Wiki::Toolkit team. All Rights Reserved.
430              
431             This module is free software; you can redistribute it and/or modify it
432             under the same terms as Perl itself.
433              
434             =head1 SEE ALSO
435              
436             L, L, L
437              
438             =cut
439              
440             1;
441