File Coverage

blib/lib/Jifty/DBI/Handle/SQLite.pm
Criterion Covered Total %
statement 56 58 96.5
branch 9 14 64.2
condition 2 5 40.0
subroutine 9 9 100.0
pod 5 5 100.0
total 81 91 89.0


line stmt bran cond sub pod time code
1              
2             package Jifty::DBI::Handle::SQLite;
3 33     33   82459 use Jifty::DBI::Handle;
  33         93  
  33         625  
4             @ISA = qw(Jifty::DBI::Handle);
5              
6 33     33   2036 use vars qw($VERSION @ISA $DBIHandle $DEBUG);
  33         73  
  33         3186  
7 33     33   210 use strict;
  33         90  
  33         36546  
8              
9             =head1 NAME
10              
11             Jifty::DBI::Handle::SQLite -- A SQLite specific Handle object
12              
13             =head1 SYNOPSIS
14              
15              
16             =head1 DESCRIPTION
17              
18             This module provides a subclass of Jifty::DBI::Handle that
19             compensates for some of the idiosyncrasies of SQLite.
20              
21             =head1 METHODS
22              
23             =head2 database_version
24              
25             Returns the version of the SQLite library which is used, e.g., "2.8.0".
26             SQLite can only return short variant.
27              
28             =cut
29              
30             sub database_version {
31 31     31 1 3734 my $self = shift;
32 31 50       152 return '' unless $self->dbh;
33 31   50     143 return $self->dbh->{sqlite_version} || '';
34             }
35              
36             =head2 insert
37              
38             Takes a table name as the first argument and assumes that the rest of the arguments
39             are an array of key-value pairs to be inserted.
40              
41             If the insert succeeds, returns the id of the insert, otherwise, returns
42             a Class::ReturnValue object with the error reported.
43              
44             =cut
45              
46             sub insert {
47 104     104 1 1411 my $self = shift;
48 104         239 my $table = shift;
49 104         532 my %args = ( id => undef, @_ );
50              
51             # We really don't want an empty id
52              
53 104         1061 my $sth = $self->SUPER::insert( $table, %args );
54 104 50       695 return unless $sth;
55              
56             # If we have set an id, then we want to use that, otherwise, we want to lookup the last _new_ rowid
57 104   33     1513 $self->{'id'} = $args{'id'} || $self->dbh->func('last_insert_rowid');
58              
59 104 50       539 warn "$self no row id returned on row creation" unless ( $self->{'id'} );
60 104         5138 return ( $self->{'id'} ); #Add Succeded. return the id
61             }
62              
63             =head2 case_sensitive
64              
65             Returns 1, since SQLite's searches are case sensitive by default.
66             Note, however, SQLite's C operator is case Isensitive.
67              
68             =cut
69              
70             sub case_sensitive {
71 187     187 1 760 my $self = shift;
72 187         1505 return (1);
73             }
74              
75             =head2 distinct_count STATEMENTREF
76              
77             takes an incomplete SQL SELECT statement and massages it to return a DISTINCT result count
78              
79              
80             =cut
81              
82             sub distinct_count {
83 11     11 1 86 my $self = shift;
84 11         13 my $statementref = shift;
85              
86             # Wrapper select query in a subselect as Oracle doesn't allow
87             # DISTINCT against CLOB/BLOB column types.
88 11         55 $$statementref
89             = "SELECT count(*) FROM (SELECT DISTINCT main.id FROM $$statementref )";
90              
91             }
92              
93             sub _make_clause_case_insensitive {
94 88     88   694 my $self = shift;
95 88         148 my $column = shift;
96 88         136 my $operator = shift;
97 88         146 my $value = shift;
98              
99 88 100       520 return ($column, $operator, $value)
100             unless $self->_case_insensitivity_valid( $column, $operator, $value );
101              
102 80         752 return("$column COLLATE NOCASE", $operator, $value);
103             }
104              
105             =head2 rename_column ( table => $table, column => $old_column, to => $new_column )
106              
107             rename column
108              
109             =cut
110              
111             sub rename_column {
112 1     1 1 709 my $self = shift;
113 1         9 my %args = (
114             table => undef,
115             column => undef,
116             to => undef,
117             @_
118             );
119              
120 1         4 my $table = $args{'table'};
121              
122             # Convert columns
123 1         15 my ($schema) = $self->fetch_result(
124             "SELECT sql FROM sqlite_master WHERE tbl_name = ? AND type = ?",
125             $table, 'table',
126             );
127 1 50       15 $schema =~ s/(.*create\s+table\s+)\S+(.*?\(\s*)//i
128             or die "Cannot find 'CREATE TABLE' statement in schema for '$table': $schema";
129              
130 1         7 my $new_table = join( '_', $table, 'new', $$ );
131 1         6 my $new_create_clause = "$1$new_table$2";
132              
133 1         5 my @column_info = ( split /,/, $schema );
134 1 50       4 my @column_names = map { /^\s*(\S+)/ ? $1 : () } @column_info;
  2         16  
135              
136 1         52 s/^(\s*)\b\Q$args{column}\E\b/$1$args{to}/i for @column_info;
137              
138 1         5 my $new_schema = $new_create_clause . join( ',', @column_info );
139 2 100       13 my $copy_columns = join(
140             ', ',
141             map {
142 1         3 ( lc($_) eq lc( $args{column} ) )
143             ? "$_ AS $args{to}"
144             : $_
145             } @column_names
146             );
147              
148             # Convert indices
149 1         8 my $indice_sth = $self->simple_query(
150             "SELECT sql FROM sqlite_master WHERE tbl_name = ? AND type = ?",
151             $table, 'index'
152             );
153 1         2 my @indice_sql;
154 1         9 while ( my ($index) = $indice_sth->fetchrow_array ) {
155 0         0 $index =~ s/^(.*\(.*)\b\Q$args{column}\E\b/$1$args{to}/i;
156 0         0 push @indice_sql, $index;
157             }
158 1         5 $indice_sth->finish;
159              
160             # Run the conversion SQLs
161 1         10 $self->begin_transaction;
162 1         4 $self->simple_query($new_schema);
163 1         8 $self->simple_query("INSERT INTO $new_table SELECT $copy_columns FROM $table");
164 1         7 $self->simple_query("DROP TABLE $table");
165 1         5 $self->simple_query("ALTER TABLE $new_table RENAME TO $table");
166 1         3 $self->simple_query($_) for @indice_sql;
167 1         9 $self->commit;
168             }
169              
170             1;
171              
172             __END__