Trailing WS crusade - got to save them bits
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / SQLite.pm
CommitLineData
843f8ecd 1package DBIx::Class::Storage::DBI::SQLite;
2
3use strict;
4use warnings;
2ad62d97 5
6use base qw/DBIx::Class::Storage::DBI/;
7use mro 'c3';
8
632d1e0f 9use DBIx::Class::Carp;
10use Scalar::Util 'looks_like_number';
11use namespace::clean;
12
d5dedbd6 13__PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker::SQLite');
6a247f33 14__PACKAGE__->sql_limit_dialect ('LimitOffset');
2b8cc2f2 15__PACKAGE__->sql_quote_char ('"');
6f7a118e 16__PACKAGE__->datetime_parser_type ('DateTime::Format::SQLite');
09cedb88 17
357eb92c 18sub backup {
19
20 require File::Spec;
21 require File::Copy;
22 require POSIX;
23
8795fefb 24 my ($self, $dir) = @_;
25 $dir ||= './';
c9d2e0a2 26
27 ## Where is the db file?
12c9beea 28 my $dsn = $self->_dbi_connect_info()->[0];
c9d2e0a2 29
30 my $dbname = $1 if($dsn =~ /dbname=([^;]+)/);
31 if(!$dbname)
32 {
33 $dbname = $1 if($dsn =~ /^dbi:SQLite:(.+)$/i);
34 }
357eb92c 35 $self->throw_exception("Cannot determine name of SQLite db file")
c9d2e0a2 36 if(!$dbname || !-f $dbname);
37
38# print "Found database: $dbname\n";
79923569 39# my $dbfile = file($dbname);
8795fefb 40 my ($vol, $dbdir, $file) = File::Spec->splitpath($dbname);
79923569 41# my $file = $dbfile->basename();
357eb92c 42 $file = POSIX::strftime("%Y-%m-%d-%H_%M_%S", localtime()) . $file;
c9d2e0a2 43 $file = "B$file" while(-f $file);
8795fefb 44
45 mkdir($dir) unless -f $dir;
46 my $backupfile = File::Spec->catfile($dir, $file);
47
357eb92c 48 my $res = File::Copy::copy($dbname, $backupfile);
c9d2e0a2 49 $self->throw_exception("Backup failed! ($!)") if(!$res);
50
8795fefb 51 return $backupfile;
c9d2e0a2 52}
53
86a51471 54sub _exec_svp_begin {
55 my ($self, $name) = @_;
56
57 $self->_dbh->do("SAVEPOINT $name");
58}
59
60sub _exec_svp_release {
61 my ($self, $name) = @_;
62
63 $self->_dbh->do("RELEASE SAVEPOINT $name");
64}
65
66sub _exec_svp_rollback {
67 my ($self, $name) = @_;
68
69 # For some reason this statement changes the value of $dbh->{AutoCommit}, so
70 # we localize it here to preserve the original value.
71 local $self->_dbh->{AutoCommit} = $self->_dbh->{AutoCommit};
72
73 $self->_dbh->do("ROLLBACK TRANSACTION TO SAVEPOINT $name");
74}
75
2361982d 76sub deployment_statements {
96736321 77 my $self = shift;
2361982d 78 my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_;
79
80 $sqltargs ||= {};
81
96736321 82 if (
83 ! exists $sqltargs->{producer_args}{sqlite_version}
84 and
85 my $dver = $self->_server_info->{normalized_dbms_version}
86 ) {
87 $sqltargs->{producer_args}{sqlite_version} = $dver;
6d766626 88 }
2361982d 89
90 $self->next::method($schema, $type, $version, $dir, $sqltargs, @rest);
91}
92
0e773352 93sub bind_attribute_by_data_type {
67b35a45 94 $_[1] =~ /^ (?: int(?:eger)? | (?:tiny|small|medium)int ) $/ix
0e773352 95 ? do { require DBI; DBI::SQL_INTEGER() }
96 : undef
97 ;
98}
99
632d1e0f 100# DBD::SQLite (at least up to version 1.31 has a bug where it will
101# non-fatally nummify a string value bound as an integer, resulting
102# in insertions of '0' into supposed-to-be-numeric fields
103# Since this can result in severe data inconsistency, remove the
104# bind attr if such a sitation is detected
105#
106# FIXME - when a DBD::SQLite version is released that eventually fixes
107# this sutiation (somehow) - no-op this override once a proper DBD
108# version is detected
109sub _dbi_attrs_for_bind {
110 my ($self, $ident, $bind) = @_;
111 my $bindattrs = $self->next::method($ident, $bind);
112
113 for (0.. $#$bindattrs) {
114 if (
115 defined $bindattrs->[$_]
116 and
117 defined $bind->[$_][1]
118 and
119 $bindattrs->[$_] eq DBI::SQL_INTEGER()
120 and
121 ! looks_like_number ($bind->[$_][1])
122 ) {
123 carp_unique( sprintf (
124 "Non-numeric value supplied for column '%s' despite the numeric datatype",
125 $bind->[$_][0]{dbic_colname} || "# $_"
126 ) );
127 undef $bindattrs->[$_];
128 }
129 }
130
131 return $bindattrs;
132}
133
732e4282 134=head2 connect_call_use_foreign_keys
135
136Used as:
137
138 on_connect_call => 'use_foreign_keys'
139
8384a713 140In L<connect_info|DBIx::Class::Storage::DBI/connect_info> to turn on foreign key
141(including cascading) support for recent versions of SQLite and L<DBD::SQLite>.
732e4282 142
143Executes:
144
8273e845 145 PRAGMA foreign_keys = ON
732e4282 146
147See L<http://www.sqlite.org/foreignkeys.html> for more information.
148
149=cut
150
151sub connect_call_use_foreign_keys {
152 my $self = shift;
153
154 $self->_do_query(
155 'PRAGMA foreign_keys = ON'
156 );
157}
158
843f8ecd 1591;
160
75d07914 161=head1 NAME
843f8ecd 162
8e766a13 163DBIx::Class::Storage::DBI::SQLite - Automatic primary key class for SQLite
843f8ecd 164
165=head1 SYNOPSIS
166
167 # In your table classes
d88ecca6 168 use base 'DBIx::Class::Core';
843f8ecd 169 __PACKAGE__->set_primary_key('id');
170
171=head1 DESCRIPTION
172
173This class implements autoincrements for SQLite.
174
175=head1 AUTHORS
176
177Matt S. Trout <mst@shadowcatsystems.co.uk>
178
179=head1 LICENSE
180
181You may distribute this code under the same terms as Perl itself.
182
183=cut