release 0.07008
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / DBI / SQLite.pm
CommitLineData
996be9ee 1package DBIx::Class::Schema::Loader::DBI::SQLite;
2
3use strict;
4use warnings;
893c0d45 5use base qw/
6 DBIx::Class::Schema::Loader::DBI::Component::QuotedDefault
7 DBIx::Class::Schema::Loader::DBI
8/;
fa994d3c 9use Carp::Clan qw/^DBIx::Class/;
942bd5e0 10use mro 'c3';
996be9ee 11
3bdcf490 12our $VERSION = '0.07008';
32f784fc 13
996be9ee 14=head1 NAME
15
16DBIx::Class::Schema::Loader::DBI::SQLite - DBIx::Class::Schema::Loader::DBI SQLite Implementation.
17
996be9ee 18=head1 DESCRIPTION
19
bc1cb85e 20See L<DBIx::Class::Schema::Loader> and L<DBIx::Class::Schema::Loader::Base>.
996be9ee 21
3b7f80f9 22=head1 METHODS
23
24=head2 rescan
25
bc1cb85e 26SQLite will fail all further commands on a connection if the underlying schema
27has been modified. Therefore, any runtime changes requiring C<rescan> also
28require us to re-connect to the database. The C<rescan> method here handles
29that reconnection for you, but beware that this must occur for any other open
30sqlite connections as well.
3b7f80f9 31
996be9ee 32=cut
33
bc1cb85e 34sub _setup {
35 my $self = shift;
36
37 $self->next::method(@_);
38
39 if (not defined $self->preserve_case) {
40 $self->preserve_case(0);
41 }
42}
43
3b7f80f9 44sub rescan {
45 my ($self, $schema) = @_;
46
47 $schema->storage->disconnect if $schema->storage;
48 $self->next::method($schema);
49}
50
69219349 51# A hack so that qualify_objects can be tested on SQLite, SQLite does not
52# actually have schemas.
53{
54 sub _table_as_sql {
55 my $self = shift;
56 local $self->{db_schema};
57 return $self->next::method(@_);
58 }
59
60 sub _table_pk_info {
61 my $self = shift;
62 local $self->{db_schema};
63 return $self->next::method(@_);
64 }
65}
66
007e3511 67sub _columns_info_for {
68 my $self = shift;
69 my ($table) = @_;
70
71 my $result = $self->next::method(@_);
a8df0345 72
dca5cd02 73 my $dbh = $self->schema->storage->dbh;
007e3511 74 local $dbh->{FetchHashKeyName} = 'NAME_lc';
75
97ab24bc 76 my $sth = $dbh->prepare(
77 "pragma table_info(" . $dbh->quote_identifier($table) . ")"
78 );
79 $sth->execute;
80 my $cols = $sth->fetchall_hashref('name');
81
692404d1 82 my ($num_pk, $pk_col) = (0);
83 # SQLite doesn't give us the info we need to do this nicely :(
84 # If there is exactly one column marked PK, and its type is integer,
85 # set it is_auto_increment. This isn't 100%, but it's better than the
86 # alternatives.
97ab24bc 87 while (my ($col_name, $info) = each %$result) {
692404d1 88 if ($cols->{$col_name}{pk}) {
89 $num_pk ++;
90 if (lc($cols->{$col_name}{type}) eq 'integer') {
91 $pk_col = $col_name;
92 }
97ab24bc 93 }
007e3511 94 }
95
96 while (my ($col, $info) = each %$result) {
268cc246 97 if ((eval { ${ $info->{default_value} } }||'') eq 'CURRENT_TIMESTAMP') {
007e3511 98 ${ $info->{default_value} } = 'current_timestamp';
dca5cd02 99 }
692404d1 100 if ($num_pk == 1 and defined $pk_col and $pk_col eq $col) {
101 $info->{is_auto_increment} = 1;
102 }
a8df0345 103 }
104
007e3511 105 return $result;
996be9ee 106}
107
108sub _table_fk_info {
109 my ($self, $table) = @_;
110
dca5cd02 111 my $dbh = $self->schema->storage->dbh;
112 my $sth = $dbh->prepare(
113 "pragma foreign_key_list(" . $dbh->quote_identifier($table) . ")"
114 );
115 $sth->execute;
996be9ee 116
dca5cd02 117 my @rels;
118 while (my $fk = $sth->fetchrow_hashref) {
119 my $rel = $rels[ $fk->{id} ] ||= {
120 local_columns => [],
121 remote_columns => undef,
bc1cb85e 122 remote_table => $fk->{table}
dca5cd02 123 };
124
bc1cb85e 125 push @{ $rel->{local_columns} }, $self->_lc($fk->{from});
126 push @{ $rel->{remote_columns} }, $self->_lc($fk->{to}) if defined $fk->{to};
dca5cd02 127 warn "This is supposed to be the same rel but remote_table changed from ",
128 $rel->{remote_table}, " to ", $fk->{table}
bc1cb85e 129 if $rel->{remote_table} ne $fk->{table};
dca5cd02 130 }
131 $sth->finish;
132 return \@rels;
996be9ee 133}
134
135sub _table_uniq_info {
136 my ($self, $table) = @_;
137
dca5cd02 138 my $dbh = $self->schema->storage->dbh;
139 my $sth = $dbh->prepare(
140 "pragma index_list(" . $dbh->quote($table) . ")"
141 );
142 $sth->execute;
996be9ee 143
dca5cd02 144 my @uniqs;
145 while (my $idx = $sth->fetchrow_hashref) {
146 next unless $idx->{unique};
4a1323d2 147
dca5cd02 148 my $name = $idx->{name};
149
150 my $get_idx_sth = $dbh->prepare("pragma index_info(" . $dbh->quote($name) . ")");
151 $get_idx_sth->execute;
152 my @cols;
153 while (my $idx_row = $get_idx_sth->fetchrow_hashref) {
bc1cb85e 154 push @cols, $self->_lc($idx_row->{name});
dca5cd02 155 }
156 $get_idx_sth->finish;
4a1323d2 157
158 # Rename because SQLite complains about sqlite_ prefixes on identifiers
159 # and ignores constraint names in DDL.
160 $name = (join '_', @cols) . '_unique';
161
dca5cd02 162 push @uniqs, [ $name => \@cols ];
163 }
164 $sth->finish;
165 return \@uniqs;
996be9ee 166}
167
168sub _tables_list {
bfb43060 169 my ($self, $opts) = @_;
5223f24a 170
996be9ee 171 my $dbh = $self->schema->storage->dbh;
5223f24a 172 my $sth = $dbh->prepare("SELECT * FROM sqlite_master");
996be9ee 173 $sth->execute;
174 my @tables;
175 while ( my $row = $sth->fetchrow_hashref ) {
26da4cc3 176 next unless $row->{type} =~ /^(?:table|view)\z/i;
522ee84e 177 next if $row->{tbl_name} =~ /^sqlite_/;
996be9ee 178 push @tables, $row->{tbl_name};
179 }
3b7f80f9 180 $sth->finish;
bfb43060 181 return $self->_filter_tables(\@tables, $opts);
996be9ee 182}
183
184=head1 SEE ALSO
185
186L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,
187L<DBIx::Class::Schema::Loader::DBI>
188
be80bba7 189=head1 AUTHOR
190
9cc8e7e1 191See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>.
be80bba7 192
193=head1 LICENSE
194
195This library is free software; you can redistribute it and/or modify it under
196the same terms as Perl itself.
197
996be9ee 198=cut
199
2001;